# The expiry of the parent node can be smaller than the one of a child node, violating the guarantee policy

Unwrapping an ENS subdomain zeroes its expiry, letting the parent re-wrap it with an expiry shorter than its existing sub-subdomains, breaking the expiry guarantee.

- Payout: Contest reward
- Severity: high
- Program: ENS
- Credited: PwnedNoMore
- Disclosed: 2022-12-13
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-07-ens-findings/issues/187
- Library page: https://bugbountylibrary.com/r/c4%3A2022-07-ens%3AH-02
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:incomplete-fix technique:source-review vuln:business-logic

**Target:** NameWrapper.sol (setSubnodeOwner/setSubnodeRecord, _getDataAndNormaliseExpiry)
**Root cause:** Unwrapping a node sets its stored expiry to 0 even when it still holds subnodes; _getDataAndNormaliseExpiry then treats oldExpiry==0 as unconstrained, so the parent can set an arbitrary (smaller) expiry on re-wrap.
**Steps:**
1. Own base.eth and setSubnodeOwner to create sub1.base.eth with max expiry.
2. Create sub2.sub1.base.eth with max expiry.
3. Unwrap sub1.base.eth so its stored expiry becomes 0 while sub2 still exists.
4. Call NameWrapper.setSubnodeOwner on base.eth for sub1.base.eth with a small expiry; oldExpiry==0 skips the maxExpiry clamp.
5. sub1.base.eth now expires before sub2.sub1.base.eth, violating the hierarchy guarantee.
**How found:** Code reading of _getDataAndNormaliseExpiry and the unwrap path: noticed oldExpiry is zeroed on burn even when subnodes exist, relaxing the maxExpiry constraint.
**Exploitation:** A domain owner manipulates wrap/unwrap state so a parent's expiry is set below a descendant's, breaking the invariant that users need only inspect a name's own fuses/expiry without traversing the hierarchy; can strand or misrepresent subdomain guarantees.
**Insight:** When an invariant is enforced by clamping against stored state, check every path that resets that state to zero (burn/unwrap) — a zeroed sentinel silently disables the clamp for nodes that still have dependents.
