Repository navigation
[#4076] Describe the gasleft() check before a randomness read - #60
Merged
Merged
Conversation
A contract whose gas after a read depends on the value can check gasleft() immediately before the read against its most expensive outcome, so that every outcome can complete. Describe the check on ISupraRandomness.next, and add LibRandomness.valueWithGasLeft, which performs the check and the read together, with Foundry tests. Documentation and a library helper only: no deployed contract imports either file, and the build embeds no metadata hash, so genesis bytecode is unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of Entropy-Foundation/smr-moonshot#4076.
What changes
The consumer guidance on
ISupraRandomness.nextsays the gas a contract spends after a read must not depend on the value in a way that makes an outcome the sender would reject the more expensive one. It offered two ways to meet that: equalise the branches, or record the outcome and settle later. This PR adds a third: checkgasleft()immediately before the read against the gas of the most expensive outcome.ISupraRandomness.nextNatSpec: describes the check: once, immediately before the first read, against the gas from that read to the end of the reading function. It states thatgasleft()is the reading frame's own gas. Because rule 2 is stated over the context address, the reading frame can be a sub-frame in the root context, such as a proxy's implementation, aDELEGATECALLlibrary, a self-call, a callback or a batchingMulticall, with a share of gas passed down to it. The check covers that frame's work only, so a reading function must not be reachable through a batching path that continues after it.LibRandomness.valueWithGasLeft(uint256 minGasAfterRead): new internal helper, for the first read of a function. It reverts with the newInsufficientGasForRead(gasLeft, minGasAfterRead)before reading when less gas remains than required, and otherwise returnsnext(). The library's header points to it.test/LibRandomness.t.sol: new. With the precompile mocked byvm.etch, the helper reads exactly once when enough gas remains. When gas is short it reverts withInsufficientGasForReadand never calls the precompile.Compatibility
No deployed contract imports either file, and
foundry.tomlsetsbytecode_hash = "none"andcbor_metadata = false, so the genesis bytecode and every CREATE2 address derived from it are unchanged. smr-moonshot does not need a new pin for this change.Testing
forge test --match-path test/LibRandomness.t.sol: 2 passed. With the check invalueWithGasLeftremoved, the short-gas test fails.forge fmt --checkon the three files: clean.The matching smr-moonshot guide and RFC changes are in Entropy-Foundation/smr-moonshot#4077.
🤖 Generated with Claude Code