# Synchronous Retargeting

> How the Retargetter restores a Position Manager's target LTV atomically inside a flash loan, in both directions.

Synchronous retargeting runs a whole [Retargetter](/protocol/retargetter/) operation inside a single transaction, funded by a flash loan. It is the path to use when the [Fund](/protocol/fund/) on the other side settles synchronously, so a subscription or a redemption can be created, committed and unlocked without waiting for an external settlement window.

The entry point is `startSyncRetargetting`, called by the owner or a rebalancer role holder:

```solidity
function startSyncRetargetting(
    address flashLoanModule,  // whitelisted IFlashLoanModule
    uint256 flashLoanAmount,  // checked against the principal cap
    address fund,             // whitelisted fund the payload may use
    bytes[] calldata data     // the steps, executed inside the callback
) external;
```

The steps are supplied as a multicall payload rather than being hardcoded, so the same entry point serves both directions and any fund shape. What keeps that safe is that the payload is committed before the loan is taken and verified inside the callback.

## The Window

```mermaid
sequenceDiagram
    participant R as Rebalancer
    participant RT as Retargetter
    participant M as Flash-loan module
    participant P as Provider (Morpho)

    R->>RT: 1. startSyncRetargetting(module, amount, fund, steps)
    RT->>RT: 2. Check cap, whitelist, commit payload digest<br/>and pre-loan balance
    RT->>M: 3. flashLoan(debtAsset, amount, payload)
    M->>P: 4. flashLoan
    P-->>M: 5. Funds
    M-->>RT: 6. Transfer funds
    M->>RT: 7. onFlashLoan(amount, payload)
    RT->>RT: 8. Verify digest, amount, full delivery
    RT->>RT: 9. Execute the steps
    RT-->>M: 10. Approve repayment
    M->>P: 11. Repay
    RT->>RT: 12. Close window: no stored order,<br/>residual within tolerance, clear state
```

Before the loan is requested the Retargetter commits three things to transient storage: the module it expects to hear back from, the hash of the exact payload, and its own debt-asset balance. In the callback it requires the caller to be that module, the payload to hash to that digest, and the live balance to have grown by the full nominal amount. A whitelisted module can therefore neither substitute its own steps nor collect the repayment approval for funds it never delivered.

Step authority lasts exactly as long as the committed payload. Outside it the module is an ordinary unauthorized caller, and so is any third party that gains execution control mid-window.

Atomicity is the settlement invariant: either the whole retarget lands (loan repaid, no order left stored, residual balances within the configured tolerance) or the transaction reverts and nothing happened.

## Increasing Leverage

The position is **below** its target LTV, so it needs more collateral. The flash loan is taken in the debt asset, subscribed into the fund, and the shares that come back are supplied as collateral. The position then borrows the flash repayment against them.

```mermaid
flowchart LR
    F["Flash loan<br/>(debt asset)"] --> S["Subscribe into the fund"]
    S --> C["Shares out<br/>(collateral)"]
    C --> SU["Supply to the position"]
    SU --> B["Borrow the repayment"]
    B --> R["Repay the flash loan"]
```

The payload is four steps:

```solidity
calls[0] = create(Order{ mode: DEPOSIT, input: amount, output: amount, ... });
calls[1] = commit();
calls[2] = unlock();
calls[3] = rebalance(RebalancingData{
    collateral: FULL_BALANCE_SENTINEL,  // supply everything the unlock returned
    debt: 0,
    operations: [
        { SUPPLY, FULL_BALANCE_SENTINEL },
        { BORROW, amount }               // exactly the flash repayment
    ]
});
```

The borrow leg is sized at exactly the flash loan amount: the flash repayment carries no yield, so nothing beyond the principal has to come back out of the position.

**Worked example.** A position holds 10,000 of quoted collateral against 5,000 of debt, an LTV of 50% against a 70% target. A 6,000 flash loan subscribes into the fund, returns 6,000 of shares, and those are supplied as collateral. The position borrows 6,000 back to repay the loan. It ends at 11,000 of debt over 16,000 of collateral, an LTV of 68.75%, at or below target.

Sizing the loan at the principal cap lands the position exactly at target. Below target the cap is bounded by the one-trip repayment bound, which for a sync window (where the flash repayment carries no yield) is `(target * K - D) / (1 - target)`, with `K` the quoted collateral and `D` the debt. On this position that is `(0.7 * 10,000 - 5,000) / 0.3 = 6,666`, and a loan of that size lands the position exactly at 70%.

## Decreasing Leverage

The position is **above** its target LTV, so it needs less debt. The order reverses: the flash loan repays debt first, which frees collateral, and that collateral is redeemed through the fund for the debt asset that repays the loan.

```mermaid
flowchart LR
    F["Flash loan<br/>(debt asset)"] --> RP["Repay position debt"]
    RP --> W["Withdraw freed collateral"]
    W --> RD["Redeem through the fund"]
    RD --> P["Proceeds<br/>(debt asset)"]
    P --> R["Repay the flash loan"]
```

The payload, again four steps:

```solidity
calls[0] = rebalance(RebalancingData{
    collateral: 0,
    debt: amount,                        // the flash loan funds the repay leg
    operations: [
        { REPAY, amount },
        { WITHDRAW, amount }             // free the collateral it unlocks
    ]
});
calls[1] = create(Order{ mode: REDEEM, input: amount, output: amount, ... });
calls[2] = commit();
calls[3] = unlock();
```

**Worked example.** The same 10,000 over 5,000 position, but with the target moved down to 30%, so an LTV of 50% is now above target. A 2,857 flash loan repays 2,857 of debt and frees 2,857 of collateral, which is redeemed for 2,857 of the debt asset and repays the loan. The position ends at 2,143 of debt over 7,143 of collateral, a hair above 30%. That is accepted: above target, a rebalance only has to strictly improve on where it started.

This direction is the one exposed to **rate drift**. The proceeds of the redemption are what repays the loan, and they settle at the realized share price rather than the price the operation was sized on. If the redemption lands even slightly short, the module's repayment pull fails and the whole transaction reverts, leaving the position untouched. Size the loan off a fresh price read.

## Constraints

- **The fund must settle synchronously.** `create`, `commit` and `unlock` all run inside one transaction, so a fund that only settles in a later epoch reverts the window. That is the atomic-revert behavior working as intended, not a partial failure.
- **The rebalance cooldown applies per call.** With a nonzero cooldown on the Position Manager, compatible legs have to be packed into a single `rebalance` step. A route that needs a fund action between two rebalances cannot run as one sync window and must run asynchronously instead.
- **No nesting.** The operation storage doubles as the entry lock, so a sync start smuggled into a payload reverts, as does an async start.
- **Direction checks apply inside the window.** The aggregate LTV must strictly improve if it ends above target, no module may worsen above target, and no module may end with debt against zero collateral. The owner bypass is evaluated on `msg.sender`, which inside a window is the module, so the checks always run there.

For the path that spans a real settlement window, see [Asynchronous Retargeting](/protocol/flows/retarget-async/).