# The tier setting parameter are unsafely downcasted from type uint256 to type uint80 / uint48 / uint40 / uint16

Juicebox NFT rewards store downcasts uint256 tier params to uint80/uint48/uint40/uint16, silently truncating contributionFloor and quantities set by the owner.

- Payout: Contest reward
- Severity: medium
- Program: Juicebox
- Credited: ladboy233
- Disclosed: 2023-01-09
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-10-juicebox-findings/issues/31
- Library page: https://bugbountylibrary.com/r/c4%3A2022-10-juicebox%3AM-02
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** JBTiered721DelegateStore.recordAddTiers tier configuration
**Root cause:** JB721TierParams fields are uint256 but are cast directly to uint80/uint48/uint40/uint16 when stored, so values above the smaller type's max are silently truncated instead of reverting.
**Steps:**
1. Deploy JBTiered721Delegate with a JB721TierParams where contributionFloor = 10000000000000000000000000 ether (exceeds uint80 max)
2. Constructor calls _store.recordAddTiers(_pricing.tiers)
3. Store casts contributionFloor to uint80, truncating the value
4. Read tier(address(_delegate),1).contributionFloor and observe truncated value 863278115882885135204352
5. Run `forge test -vv --match testJBTieredNFTRewardDelegate_mintFor_mintArrayOfTiers_downcast_POC`
**How found:** Code review of the initialize -> recordAddTiers callstack, noticing struct fields are uint256 while the stored struct uses narrower types, then writing a Foundry PoC to confirm truncation.
**Exploitation:** Owner-configured floor price above uint80 max is truncated to a much smaller value, letting minters pay far less than intended for the NFT; similarly initialQuantity/votingUnits/reservedRate truncate.
**Insight:** When a config struct uses uint256 but the persisted struct uses narrower types, check every field for silent truncation; a floor price above uint80 max wraps to a tiny value, turning a config bug into an underpayment/discount primitive.
