Slab V2
SlabMachineV2.sol
This document summarizes the security-focused review of SlabMachineV2.sol, including cross-contract analysis with SlabLocker and RarityCalculatorV2. The review focuses on user pull/sell-back lifecycle, RNG callbacks, and multi-machine locker interaction assumptions.
[HIGH] Sell-Back Does Not Replenish Pullable Inventory (Cross-Contract Lifecycle Break)
From the machine perspective, the intended lifecycle is:
- User pulls token from machine (token leaves locker custody).
- Machine creates buyback offer.
- User sells token back via
sellBack. - Locker re-adds token into machine pools.
In current implementation, step 4 fails because locker assignment state is cleared during withdrawal. sellBack calls slabLocker.depositFromSender, but locker no longer has any machine assignments recorded for that token, so the token is returned to locker custody without being re-added to any machine pool.
Impact:
- Sold-back tokens become unpullable until owner manually reassigns via
addTokenIds. - Buyback recirculation degrades over time.
- This directly conflicts with expected automated inventory loop.
Recommended Solution
Coordinate fix with SlabLocker:
- Preserve token-to-machine assignment membership while token is out of custody.
- Remove only availability from active pools on withdrawal.
- Re-add to assigned pools on
depositFromSender.
This is a shared machine+locker issue and should be treated as one remediation item.
[MEDIUM] RNG Rotation Can Strand Pending Pull Requests
setRandomNumberGenerator allows owner to switch RNG contracts at any time. Pending requests are validated in callback by:
msg.sender == address(randomNumberGenerator)
If owner changes RNG while requests are pending, callbacks from the old RNG revert with InvalidSender, and pending requests can become unfulfillable (depending on RNG implementation and replay capabilities). Users have already paid in pull via slabLocker.settle.
Recommended Solution
Use one of these guardrails:
- Block RNG change while there are unresolved pending requests, or
- Maintain a temporary allowlist for previous RNG until outstanding request IDs are resolved.
At minimum, document this as an operational safety rule and add tests.
[MEDIUM] setMachineConfig Accepts Unsafe Values Without Validation
setMachineConfig has no checks for:
maxPulls == 0(all pulls become impossible),buybackPercentage > 100(economic overpayment risk),- extreme
buybackExpiryvalues.
Owner-only does reduce direct attack surface, but this is a high-impact configuration footgun.
Recommended Solution
Add bounds validation and explicit errors, for example:
maxPulls > 0buybackPercentage <= 100(or protocol-specific cap)- sane bounds for
buybackExpiry
[LOW] Missing Explicit RandomNumberGeneratorNotSet Check in pull
The interface defines RandomNumberGeneratorNotSet, and docs state machine should not open without RNG set. In implementation, pull calls randomNumberGenerator.requestRandomNumbers directly with no explicit pre-check. If RNG is unset, users get a low-signal revert path instead of the defined custom error.
Recommended Solution
Add an explicit check in _pull (or _checkIsActive) and revert with RandomNumberGeneratorNotSet when unset.
Summary
| Severity | Count | Focus |
|---|---|---|
| High | 1 | Sell-back inventory recirculation breaks due locker assignment state handling. |
| Medium | 2 | RNG rotation risk on pending requests; unsafe config values. |
| Low | 2 | Missing explicit RNG-not-set revert; multi-machine coverage gap. |
SlabMachineV2 is generally well-structured, especially around callback gas and failure refunds. The main issue is lifecycle coupling with SlabLocker during sell-back restocking, which should be resolved before production scale-out.