> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mystockline.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Open a loan

> PositionRouter.openPosition pulls stock, supplies it, and borrows USDG in one transaction.

`PositionRouter` never holds a position. The loan stays on the user. The router must be an operator before it can borrow.

Addresses: [Addresses](/resources/addresses), Robinhood Chain testnet. ABI: [`PositionRouter.json`](/abis/PositionRouter.json).

<Steps>
  <Step title="Approve the router as operator">
    Required for `borrow` and `withdrawCollateral` on behalf of the user. `setOperatorWithSig` exists for EOAs that need one flow.

    <CodeGroup>
      ```typescript theme={"system"}
      import { parseAbi } from "viem"
      import { addresses } from "./addresses" // Addresses, testnet

      const coreAbi = parseAbi([
        "function setOperator(address operator, bool approved)",
        "function isOperator(address account, address operator) view returns (bool)",
      ])

      await wallet.writeContract({
        address: addresses.stockline,
        abi: coreAbi,
        functionName: "setOperator",
        args: [addresses.positionRouter, true],
      })
      ```

      ```solidity theme={"system"}
      interface IStockline {
          function setOperator(address operator, bool approved) external;
      }

      // User calls this on Stockline, not on the router.
      // IStockline(core).setOperator(router, true);
      ```
    </CodeGroup>
  </Step>

  <Step title="Permit or approve the stock">
    `openPosition` pulls `supplyAmount` of the book's collateral with `transferFrom`. Pass a Permit if the token supports it. `deadline = 0` skips permit.

    The book must be `borrowingEnabled` and `regime == LIVE`.
  </Step>

  <Step title="Open in one transaction">
    <CodeGroup>
      ```typescript theme={"system"}
      const routerAbi = parseAbi([
        "function openPosition(uint16 bookId, uint256 supplyAmount, uint256 borrowAmount, (uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) permit)",
      ])

      const bookId = 8
      const supplyAmount = 10n * 10n ** 18n
      const borrowAmount = 1n * 10n ** 18n
      const emptyPermit = { value: 0n, deadline: 0n, v: 0, r: "0x" + "00".repeat(32), s: "0x" + "00".repeat(32) }

      await wallet.writeContract({
        address: addresses.positionRouter,
        abi: routerAbi,
        functionName: "openPosition",
        args: [bookId, supplyAmount, borrowAmount, emptyPermit],
      })
      ```

      ```solidity theme={"system"}
      struct PermitData {
          uint256 value;
          uint256 deadline;
          uint8 v;
          bytes32 r;
          bytes32 s;
      }

      interface IPositionRouter {
          function openPosition(uint16 bookId, uint256 supplyAmount, uint256 borrowAmount, PermitData calldata permit) external;
      }
      ```
    </CodeGroup>
  </Step>
</Steps>

## What can go wrong

* `NotOperator` if you skipped step 1 and `borrowAmount > 0`.
* `RegimeBlocked` on weekends, holidays, halts, corporate-action windows, and sequencer-down.
* `Paused` if the guardian flipped the core.
* `BorrowingDisabled` while the book is still closed. Launch default is off. Testnet may have flipped it.
* `Unhealthy` / cap errors if `borrowAmount` exceeds `RiskLens.maxBorrow` or the book/issuer cap.
* Leftover stock is swept back to the caller. The router must end at zero balances.

## Parameters

| Parameter                          | Type                          | Meaning                                                                                                                                       |
| ---------------------------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `bookId`                           | `uint16`                      | The book to supply into and borrow from. Resolve it from [Books and tiers](/concepts/books-and-tiers) or `RiskRegistry.bookIdOf(collateral)`. |
| `supplyAmount`                     | `uint256`                     | Raw stock amount to pull with `transferFrom` or permit. Can be `0` to borrow against stock already supplied.                                  |
| `borrowAmount`                     | `uint256`                     | USDG to borrow, in USDG decimals (18 on testnet). Can be `0` to supply only.                                                                  |
| `permit.value`                     | `uint256`                     | Permit allowance. Usually equal to `supplyAmount`.                                                                                            |
| `permit.deadline`                  | `uint256`                     | Permit expiry. `0` skips permit and uses a prior `approve`.                                                                                   |
| `permit.v`, `permit.r`, `permit.s` | `uint8`, `bytes32`, `bytes32` | EIP-2612 signature parts. Ignored when `deadline` is `0`.                                                                                     |

Launch default for `borrowingEnabled` is off. Testnet may have flipped it. Read the flag on [Parameters](/resources/parameters) rather than trusting the ARCHITECTURE.md launch prose.

Next: [Repay and withdraw](/developers/positions/repay-and-withdraw), [Zap](/developers/positions/zap).
