> ## 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.

# Solidity

> Integrate from a contract.

Call `RiskLens` and `PositionRouter` from a contract the same way the app does from viem.

The router must be an operator before it can borrow. Your contract, if it holds the stock, must `setOperator` on `Stockline` or hold the position itself and call the core.

<CodeGroup>
  ```solidity theme={"system"}
  // SPDX-License-Identifier: MIT
  pragma solidity 0.8.28;

  interface IRiskLens {
      function maxBorrow(address account) external view returns (uint256);
      function liquidationPrice(address account, uint16 bookId) external view returns (uint256);
  }

  interface IPositionRouter {
      struct PermitData { uint256 value; uint256 deadline; uint8 v; bytes32 r; bytes32 s; }
      function openPosition(uint16 bookId, uint256 supplyAmount, uint256 borrowAmount, PermitData calldata permit) external;
  }

  contract StocklineClient {
      IRiskLens public immutable lens;
      constructor(IRiskLens lens_) { lens = lens_; }
      function power(address account) external view returns (uint256) {
          return lens.maxBorrow(account);
      }
  }
  ```

  ```typescript theme={"system"}
  // Deploy the client with riskLens from /resources/addresses
  ```

  ```tsx theme={"system"}
  // Frontends should still read RiskLens directly. Do not add an extra hop for views.
  ```
</CodeGroup>

Addresses: [Addresses](/resources/addresses). Never hardcode production ids from a testnet snippet.

`Zap` and `PositionRouter` must hold zero balances after a call. If you wrap them, sweep leftovers back in the same transaction.

Do not call `LiquidationModule.liquidate` yourself. It reverts `NotCore`. Submit through `Stockline.liquidate`.

## What can go wrong

* Missing operator grant: `NotOperator`.
* Weekend: `RegimeBlocked`.
* Guardian pause: `Paused`.
* Book still closed: `BorrowingDisabled`.

Next: [Open a loan](/developers/positions/open-loan), [Zap](/developers/positions/zap).

A contract integration is a user of the same action table as the app. `repay` and `supplyCollateral` stay live in every regime and under guardian pause. `borrow` and `withdrawCollateral` require LIVE and not paused. `liquidate` requires LIVE or DARK and not paused.

If your contract holds stock and wants to open a loan in one transaction, either call `Stockline` directly or `setOperator` for `PositionRouter` and then `openPosition`. Do not leave balances on the router. The invariant is that PositionRouter, Zap, and CreatorFeeRouter hold zero after any call sequence.

Permit on the stock token is optional. `deadline = 0` skips permit and uses `transferFrom`. Approve first if you skip permit.

Read RiskLens from offchain for UI. Onchain views of `maxBorrow` are fine for a keeper or a wrapper that must not over-borrow. Never send `uiMultiplier` into those checks.
