# Unbounded live terms on loan actions

Accepting calls that read live terms with no caller-supplied bound or deadline

_Area: Smart contract access control and control flow. Seen in 2 disclosed reports; latest 2024-07-25. Updated 2026-10-31._

## How it works
A loan, roll, or renewal action reads terms from live contract state (current rate, current expiry, current owner) instead of from values the caller committed to. The assumption that "the terms I saw when I decided are the terms I get" breaks: between decision and execution, anyone can change those terms or the timing. With no max/min bound and no deadline, the transaction executes against whatever state exists at inclusion.

## Where it shows up
- Roll/accept flows where the accepting call reads terms set by a separate call, with no caller-supplied bound on the accepted value [E2](https://bugbountylibrary.com/r/sherlock%3A2023-08-cooler%3AM-4.md)
- Renew/extend functions with no timestamp check against an expiry or grace-period boundary [E3](https://bugbountylibrary.com/r/c4%3A2025-01-initia-move%3AH-04.md)
- Lifecycle boundary checks in different functions using different comparison operators (`<` vs `>`) on the same timestamp [E1](https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-15.md)
- Any mutation path (renew, extend, transfer) that omits a time bound enforced on the claim path [E3](https://bugbountylibrary.com/r/c4%3A2025-01-initia-move%3AH-04.md)
- A separate setter that writes terms later consumed by a user's transaction [E2](https://bugbountylibrary.com/r/sherlock%3A2023-08-cooler%3AM-4.md)

## How to review
For each accepting/rolling/renewing call, identify every value it reads from live state. The invariant: each such value must be constrained by a caller-supplied bound (max rate, max cost) or a deadline, and the call must revert if live state exceeds it. Separately, for every lifecycle boundary, list all functions that gate on the same timestamp and confirm they agree at equality — a timestamp satisfying both "expired" and "not due" is a state-machine gap [E1](https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-15.md). For grace periods, confirm every mutation path enforces the same `expiration + grace` bound as the claim path [E3](https://bugbountylibrary.com/r/c4%3A2025-01-initia-move%3AH-04.md).

## Variants seen
- Boundary-operator mismatch: expiry check uses `<`, liquidation check uses `>`, so the equality timestamp passes both, letting a liquidated loan be re-borrowed [E1](https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-15.md)
- Front-run term swap: lender re-sets terms before borrower's roll executes, no slippage bound on accepted terms [E2](https://bugbountylibrary.com/r/sherlock%3A2023-08-cooler%3AM-4.md)
- Missing grace-period bound: anyone can extend an expired domain, blocking a new buyer's registration [E3](https://bugbountylibrary.com/r/c4%3A2025-01-initia-move%3AH-04.md)

## Impact and severity
Led to unfavorable terms forced on borrowers [E2](https://bugbountylibrary.com/r/sherlock%3A2023-08-cooler%3AM-4.md), blocked registrations for new buyers [E3](https://bugbountylibrary.com/r/c4%3A2025-01-initia-move%3AH-04.md), and state corruption that bricked auction settlement [E1](https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-15.md). Severity rises when the action is permissionless and the race is decided by mempool ordering, since that makes the outcome reliable rather than probabilistic.

## Why fixes fail
Fixing only the claim path leaves renew/extend paths open [E3](https://bugbountylibrary.com/r/c4%3A2025-01-initia-move%3AH-04.md); fixing one boundary check without reconciling the paired check leaves the equality gap [E1](https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-15.md).

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2024-04-gondi%3AH-15.md
- E2: https://bugbountylibrary.com/r/sherlock%3A2023-08-cooler%3AM-4.md
- E3: https://bugbountylibrary.com/r/c4%3A2025-01-initia-move%3AH-04.md
