Normal behavior: The contract should permanently reference a single BidBeasts NFT contract address that is assigned during deployment and cannot be changed afterwards. Callers and users expect that marketplace logic always interacts with the same NFT contract address provided at deployment.
Specific issue: The BidBeastsNFTMarket::BBERC721 field is declared as a non-immutable state variable and is only assigned in the constructor. Although the current source code contains no setter, marking the variable non-immutable leaves room for accidental or intentional future reassignment (for example by adding a setter, introducing an upgrade that modifies storage, or by incorrectly-written proxy/delegatecall logic). This weakens the guarantee that the marketplace will always point to the original NFT contract and increases the attack surface and chance of human error.
Likelihood:
Reassignment happens during future maintenance or upgrades when a developer adds a setter or modifies initialization logic without realizing the security implication.
Reassignment occurs during an upgrade/proxy flow or via a badly-written delegatecall path that unintentionally writes to this storage slot.
Impact:
Marketplace operations (e.g., mint, transferFrom, buy, etc.) may be redirected to a different, attacker-controlled or unintended NFT contract — causing users to interact with incorrect token logic, lose funds, or receive unexpected tokens.
Trust assumptions are broken: users may mint or trade NFTs under the assumption they interact with Collection A while the marketplace actually points to Collection B, enabling confusion, scams, or economic damage to users and reputation damage to the project.
Note: The first demo shows that given a writable declaration, a setter could be added and would compile; the second demo shows that marking the variable
immutablemoves the enforcement into the compiler and prevents future reassignment at compile time.
Additional recommendations (defense-in-depth):
If the design requires the NFT address to be changeable in the future, introduce a controlled, auditable pattern instead:
Provide a restricted setter protected by a robust access control (e.g., onlyOwner where owner is a multisig) and require emitting an event on every update.
Combine with a timelock or multisig approval flow to prevent immediate unilateral reassignments.
Add unit tests that assert the NFT address is immutable (or that setter is restricted) and add fuzzing/invariant tests to catch accidental writes to that storage slot.
During audits, include checks for delegatecall, upgradeability proxies, and any patterns that could write to arbitrary storage slots; ensure storage layouts are well-documented to prevent accidental overwrites after upgrades.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.