Skip to main content

Module unsafe_oz_erc721_mint

Module unsafe_oz_erc721_mint 

Source

StructsΒ§

AccountCodeChangeFinder πŸ”’
CalleeCollector πŸ”’
Collects every call in a subtree as its resolved target and its argument list, from which the caller reads what the delegation binds to the mint’s parameters.
GuardWalk πŸ”’
The straight-line reading of a body: coverage once a guard has run on the path, pending while a delegated mint has run with no guard before or after it yet, failed once a path may leave the function successfully with such a mint standing, escaped once one may leave before any guard ran.
MintCallFinder πŸ”’
ModifierCoverage πŸ”’
Guard state in effect while a function body runs after expanding its modifier prefixes and accounting for guaranteed modifier tails.
MutationFinder πŸ”’
Finds an assignment to var anywhere in a subtree, conservatively including assembly.
UnsafeMintTarget πŸ”’
An unsafe mint target and whether every recursive hop preserves the recipient and token it receives. A callback guard needs both guarantees, while a code-less-recipient proof needs only the first.

EnumsΒ§

GuardCoverage πŸ”’
How a path established that the recipient can receive the mint. Callback evidence remains valid when summarizing a guard helper, while a code-less proof must be retired once a call could deploy code at the recipient address. Whether the evidence can cover a future mint is tracked separately by GuardWalk::future_coverage.
SelectorEncoding πŸ”’
The representation of a selector-sized constant at one conversion step.

ConstantsΒ§

ERC721_RECEIVED πŸ”’
The ERC721 answer meaning the recipient accepts the token, onERC721Received’s selector.
OPENZEPPELIN_PACKAGE_ROOTS πŸ”’
The package-root directory names of the OpenZeppelin distributions: the npm scope and the git-submodule roots. Provenance is judged against a full path component so a same-name contract under a merely-substring path such as src/not-openzeppelin/ is not recognized.

StaticsΒ§

UNSAFE_OZ_ERC721_MINT

FunctionsΒ§

acceptance_coverage πŸ”’
The condition of a require/assert that passes only if the recipient can receive the token: the recipient is proven code-less, the hook comparison succeeds, or the account short circuit to.code.length == 0 || hook == sel accepts either case.
argument_bound_to_parameter πŸ”’
The argument a call binds to the callee’s parameter at index. Named arguments come in source order, which is not the parameter order: _mint({id: tokenId, to: to}) hands the token to to all the same.
assigns_to πŸ”’
Whether an assignment target names var, directly or as one component of a tuple.
body_guards πŸ”’
walk_guards on a callee’s body, against the parameters the recipient and the token landed on: the callee guards when a guard ran before any possible successful exit, which is what its caller relies on. bypass says the wrapped body can leave through an assembly return, making an uncovered placeholder such an exit. seen cuts recursion cycles.
bound_guard_parameters πŸ”’
The callee parameters that receive the caller’s recipient and token identities.
branch_always_reverts πŸ”’
Whether executing stmt always reverts, undoing everything the transaction did. Only a revert counts, the guards being matched without an order: see may_return for the escapes that leave the transaction standing.
callable_contains_frame_ending_assembly πŸ”’
Whether a resolved same-frame callable or one of its applied modifiers can reach assembly. The recursion set is a path stack so independent calls are summarized independently.
callable_may_change_account_code πŸ”’
Whether a statically known same-frame callable can create code, directly, through an applied modifier, or through another internal call. Recursion cycles alone do not create code; any opaque, virtual, or external state-changing call reached by the body remains conservative.
callee_guards_recipient πŸ”’
A call handing the checked identities to a same-frame function or modifier whose body proves acceptance for the parameters they land on. Callback guards receive distinct recipient and token identities; the recipient-only pass supplies the same identity in both slots, allowing an address-only helper to prove that it has no code. Arguments are matched by is_exactly_var against the callee’s parameters and by parameter name for named arguments.
contains_delegation πŸ”’
Whether a subtree holds a call dispatching to one of the delegated mints.
contains_frame_ending_assembly πŸ”’
Whether a subtree can reach an assembly block in the same EVM frame, directly or through an internal call. An assembly return leaves the frame without running a later revert or what an outer modifier holds after its placeholder. Every assembly block is treated as capable of doing so, conservatively matching may_return.
contains_placeholder πŸ”’
Whether a subtree holds the _; placeholder of a modifier.
expr_contains_frame_ending_assembly πŸ”’
contains_frame_ending_assembly over an expression, used for a refusal condition that may itself leave before either branch runs.
expr_may_change_account_code πŸ”’
Whether an expression may change the code installed at an account. Pure and view calls are stable (external ones execute through STATICCALL), while nonpayable/payable calls and contract creation can run CREATE/CREATE2. Calls to the delegated mint itself are excluded: the code-length proof is needed precisely until that call begins, though calls in its arguments are still inspected.
expr_mutates_var πŸ”’
mutates_var over an expression, for the condition of an if, which the If arm reaches before the statement arm ever sees it: if ((tokenId = x) > 0) {} reassigns as surely as a bare statement, and the condition runs whichever branch is taken.
function_reaches πŸ”’
guard_expr_coverage πŸ”’
A statement expression that guards the recipient and the token: require/assert on an acceptance condition, or an internal call handing both to a helper that does. Only the condition is read: a hook call sitting in the revert message decides nothing, and neither does one in any other argument. An external helper would ask from a different contract and cannot establish that the recipient accepts the minting contract’s callback.
guard_extra_args_may_change_account_code πŸ”’
Whether a recognized require/assert has another argument that may change account code. The first argument is the closed-form acceptance condition itself; its receiver callback is part of the proof. Message and other arguments are not, and Solidity does not guarantee they run before the condition’s code-length snapshot.
is_canonical_erc721 πŸ”’
The OpenZeppelin contracts whose _mint skips the receiver check. ERC721 and ERC721Upgradeable declare the unchecked _mint; in the v4 line, ERC721Consecutive and ERC721ConsecutiveUpgradeable override it with a construction guard that forwards to the base through super._mint, still without a receiver check, so resolving to them is just as unsafe. In v5 the Consecutive extension overrides _update instead, and the two extra names match nothing.
is_code_length_test πŸ”’
recipient.code.length compared against zero, for one polarity. Nothing else may ride along: in to.code.length > 0 && id == 5 the second operand decides whether the branch runs.
is_exactly_var πŸ”’
The variable itself, behind parentheses and value-preserving conversions: to, (to), IERC721Receiver(to), payable(to). Anything else, guardians[to] or IERC721Receiver(other), is a different value, and asking it about the token says nothing about the recipient.
is_hook_call_on πŸ”’
recipient.onERC721Received(..., token, ...): the hook, asked of the recipient itself and about the delegated token itself. A recipient may accept one token and refuse another, so an answer about a different id, the hook’s third parameter, decides nothing for the minted one.
is_hook_comparison πŸ”’
recipient.onERC721Received(...) <op> x, and nothing else. The comparison must be the whole expression: in to == trusted || hook(to) == selector the hook never runs for trusted. The other operand must be able to hold the accepting answer, and must not be a hook call itself, which would compare the recipient against itself.
is_openzeppelin_source πŸ”’
Whether a source file belongs to an OpenZeppelin package, judged by a full path component.
is_override_delegation_helper πŸ”’
is_received_selector πŸ”’
Whether an expression is the accepting answer. Comparing the hook’s answer against anything else mints to a recipient that answered something the ERC721 receiver interface calls a refusal, so only an operand this reads and finds equal to the selector is credited: the literal, a conversion of it, a constant holding it, or a selector member resolving to the receiver hook itself. The member is resolved rather than matched by name: spelled on a same-name function of another shape, .selector is a different value, which a recipient answering it never accepted with. A value settled at deployment or at runtime, an immutable or a state variable, is unknown here and does not exempt.
is_receiver_hook πŸ”’
Whether a resolved declaration is the ERC721 receiver hook: the exact name, the exact (address, address, uint256, bytes) shape, and an externally callable declaration of a non-library contract. The name alone would let a call to a same-name function of an unrelated interface, which answers on a different selector, pass as the check, and an attached library or free function runs in the minting contract without any external call, so resolving to one says nothing about the recipient.
is_recipient_code_length πŸ”’
recipient.code.length.
is_revert_call πŸ”’
revert(...), require(false, ...) and assert(false).
is_unresolved_internal_pointer_call πŸ”’
Whether a call dispatches through an internal function-pointer variable whose target is not available from the callee type. Such a target may contain assembly that leaves the frame, so exit analysis must treat the call conservatively.
keeps_its_value πŸ”’
Whether the variable cannot change between the delegation and the callback guard. An intervening call, including one inside a recursively delegated override, can reenter and mutate a state variable after the mint reads it but before the guard does. A local, a parameter, a constant or an immutable cannot be moved that way.
may_return πŸ”’
Whether a statement may leave the function while keeping what the transaction already did. A return does, and so does the EVM return/stop an assembly block can hold. Only the statements that provably cannot leave answer no, so a guard is never credited on a path this analysis does not read.
modifier_body_sides πŸ”’
The statements before and after a modifier’s single top-level placeholder. More complicated expansion shapes are left uncredited rather than guessing which paths execute the body.
modifier_coverage_at_body πŸ”’
Coverage in effect when a function body starts after expanding its modifiers in declaration order. Prefixes are walked in execution order so calls in an inner modifier can retire an outer code-length snapshot. A proven tail guard is represented as stable callback coverage while walking the body: it runs after the body and can revert every mint the body made, unless assembly in the body or an inner modifier can bypass it.
mutates_var πŸ”’
Whether a statement assigns to var: var = x, var += x, var++, delete var, or var as a component of a tuple assignment. An assembly block is treated as an opaque assignment, since it can rewrite Solidity locals outside the HIR expression tree. Identity here is by variable, not by value, so a guard that checked var says nothing once var is reassigned: the delegation then credits a value or an address the guard never saw, though the two spell the same variable.
peel_value_preserving πŸ”’
The expression carrying the same value, behind parentheses, payable(...) and casts to an address or contract type, which map every operand to itself. A numeric cast such as uint8(...) truncates: the minted address is then usually not the checked one, so it is not peeled.
resolved_callee πŸ”’
The function a call expression dispatches to, as the type checker resolved it.
resolved_function πŸ”’
The function a bare expression names, as the type checker resolved it.
resolved_internal_callee πŸ”’
The declaration a call executes in the current EVM frame. A public function called by name is internal here, while this.f() and other external calls run in another frame whose assembly return cannot bypass the caller’s later statements.
selector_cast_preserves πŸ”’
Whether a cast preserves the recognized selector’s value and byte alignment. A recognized integer is exactly the positive selector, so any integer width of at least 32 bits keeps it. Crossing between right-aligned integers and left-aligned fixed bytes is only trusted at the four-byte boundary.
stmt_may_change_account_code πŸ”’
expr_may_change_account_code over a whole statement. Inline assembly is opaque and may deploy code even when it contains no HIR call expression.
variable_of πŸ”’
The variable an expression is, behind the same conversions is_exactly_var sees through, or nothing when the expression is not a plain variable.
walk_guards πŸ”’
Reads a body in statement order and judges the delegated mints against the guards. A code-less proof may cover a later delegation, but a callback must run after ownership is established to match _safeMint: the receiver can inspect ownerOf, balances, or reenter during the hook. Such a callback covers delegations still pending, the revert undoing them, unless a statement in between may leave the function successfully, keeping the unacknowledged token: super._mint(to, id); if (id == 0) return; require(hook...) walks out with token zero standing.
walk_one πŸ”’
walk_guards on a single statement.