# Upgrading modules via executeAction() will brick all existing rentals

Upgrading a module via Kernel::executeAction() leaves old rentals' escrowed assets in the old module with no migration path, so stopRent reverts and funds are locked.

- Payout: Contest reward
- Severity: medium
- Program: reNFT
- Credited: juancito
- Disclosed: 2024-03-20
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2024-01-renft-findings/issues/397
- Library page: https://bugbountylibrary.com/r/c4%3A2024-01-renft%3AM-07
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** Kernel module upgrade / PaymentEscrow module
**Root cause:** Kernel::executeAction() UpgradeModule reconfigures policies and initializes new modules but performs no data migration or asset transfer; old module storage (rental states, escrowed balances) is orphaned.
**Steps:**
1. Create and fulfill a BASE rental order so ERC20 payment is escrowed in PaymentEscrow (ESCRW).
2. Deploy a new PaymentEscrow proxy via create2Deployer with MODULE_PROXY_INSTANTIATION init.
3. Call `kernel.executeAction(Actions.UpgradeModule, address(NEW_ESCRW))` as deployer.
4. Warp past rental expiration; assert STORE.orders(orderHash)==true and old ESCRW still holds 100 ERC20 while NEW_ESCRW holds 0.
5. Call `stop.stopRent(preUpgradeRental)` as alice — reverts, assets locked.
**How found:** Code reading of Kernel::executeAction() upgrade path: noticed it reconfigures policies/initializes modules but never migrates storage or transfers assets, then wrote an integration test to confirm old rentals can't be stopped and funds remain in the old escrow.
**Insight:** When auditing upgradeable/modular protocols, check whether the upgrade routine migrates module-held state and assets; modules that custody funds (escrow) or track per-user state need explicit migration or a drain/stop path, otherwise upgrades orphan live positions.
