What the review
looks for.
high
Likely to lose funds or hand control to the wrong account.
Authorization with tx.origin
tx.origin is the account that started the transaction, so any contract that account calls can act with its rights.
rule id: tx-origin
Low-level call result ignored
A failed .call does not revert on its own; ignoring the returned flag treats a failed payment as a sent one.
rule id: unchecked-call
Mint without a caller check
A public mint function that never looks at msg.sender lets anyone create supply.
rule id: unguarded-mint
delegatecall present
delegatecall runs foreign code with this contract's storage and balance. It needs a fixed, trusted target.
rule id: delegatecall
medium
Can go wrong under specific conditions; worth fixing before value arrives.
State written after an external call
Updating balances after sending ETH or calling out opens the door to re-entrancy. Write state first, call last.
rule id: state-after-call
Constructor reads msg.sender
Deployed through WerboPress, the constructor's msg.sender is the press, not you. Pass the owner as an argument.
rule id: constructor-sender
Randomness from block values
Timestamps, block hashes and prevrandao can be predicted or nudged; they are not a fair source of chance.
rule id: weak-randomness
ETH can come in but never leave
The contract accepts ETH but has no path that sends ETH out, so anything received stays forever.
rule id: locked-ether
Raw ecrecover
ecrecover returns address(0) for bad signatures and accepts both s values. Check for zero and bound s.
rule id: ecrecover
selfdestruct present
Since Cancun it no longer deletes code except in the creating transaction, and it is deprecated.
rule id: selfdestruct
low
Robustness and precision issues that usually cost gas or surprise users.
ETH sent with transfer or send
Both forward a fixed 2300 gas, which smart-contract wallets often need more than. Use call and check the result.
rule id: transfer-send
Loop over a growing storage array
If the array can grow without limit, the loop can one day cost more gas than a block holds.
rule id: storage-loop
Constructor address not checked for zero
An empty address argument usually means a typo, and immutable values cannot be fixed afterwards.
rule id: zero-address
Division before multiplication
Integer division rounds down; dividing first throws away precision that the multiplication would have kept.
rule id: divide-first
info
Things to know and decide on purpose.
block.number used
On Arbitrum-based chains such as Robinhood Chain, block.number follows the parent chain, not this chain's blocks. Use block.timestamp for time.
rule id: block-number
Floating pragma
^0.8.x lets a later compiler build it. Fine for drafts; pin the exact version you tested before deploying.
rule id: floating-pragma
Inline assembly
Assembly skips the compiler's safety checks. Read each block line by line.
rule id: assembly
unchecked arithmetic
Inside unchecked blocks overflow wraps silently. Each one needs a reason it cannot overflow.
rule id: unchecked-math
State changes without events
Without events, wallets, explorers and indexers cannot follow what the contract did.
rule id: no-events
One account holds special rights
Everything the owner can do depends on one key. Say so plainly to users, or use a multisig as the owner.
rule id: single-owner
No SPDX license line
Explorers and other builders look for an SPDX-License-Identifier comment at the top of the file.
rule id: missing-license