> For the complete documentation index, see [llms.txt](https://kittypunch.gitbook.io/kittypunch-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kittypunch.gitbook.io/kittypunch-docs/protocols-and-products-abstract/kona-lend/leverage-trading/agent-integration-spec.md).

# Agent Integration Spec

### Why this matters

DeFi is moving toward autonomous agents — bots and AI systems that can read market state, reason about risk, and execute strategies without human intervention at every step. The KonaLooper contract on Abstract was designed to make that easy.

A single contract gives agents everything they need: market discovery, trade quoting, position inspection, and execution — all through standard `eth_call` reads and signed transactions. No proprietary APIs. No off-chain dependencies. No authentication layers. Just an EVM contract with a clean interface.

#### What agents can build with this

* **Yield optimization** — Scan lending rates across markets, identify positive carry, and open same-asset yield loops that multiply supply APY while earning protocol rewards on both sides of the position.
* **Directional strategies** — Go long WETH or PENGU against stablecoins, or short them, with leverage up to 4x. Agents can combine on-chain oracle reads with their own signal models.
* **Risk management** — Monitor health factors across user positions, trigger `leverageDown` to reduce exposure before liquidation, or `closeLeverage` to exit entirely when conditions deteriorate.
* **Portfolio rebalancing** — Adjust leverage targets dynamically as market conditions shift. Quote the cost of rebalancing before committing.
* **Position tracking** — Index `LeverageUp`, `LeverageDown`, and `FeeCollected` events to reconstruct full position history, calculate realized PnL, and build dashboards — all from on-chain data.

***

### Architecture at a glance

KonaLooper is a **stateless flash loan orchestrator** deployed on Abstract Mainnet (chain ID `2741`). It does not custody funds. Here's the flow:

1. User deposits collateral (e.g. 100 PENGU)
2. KonaLooper takes a flash loan for the amplified amount
3. Supplies total collateral to the Kona Lend pool
4. Borrows against it (same asset for yield loops, or a different asset for directional trades)
5. Repays the flash loan from borrow proceeds

All of this happens atomically in one transaction. After execution, the user's wallet holds the collateral and debt positions directly in the lending pool. The looper holds nothing.

***

### Deployed contracts

| Contract                                            | Address                                       |
| --------------------------------------------------- | --------------------------------------------- |
| **KonaLooper** (ERC-1967 proxy — use for all calls) | `0x09A4518945C9cD484B5eac3FACf4A5B0bdd3A5bc`  |
| KonaLooper implementation (verification only)       | `0x39fb6d7B5566d2F844863F2AaE1C7C74896e0B31`  |
| PunchSwap router (swap path, used internally)       | `0x441E0627Db5173Da098De86b734d136b27925250`  |
| Kona Lend pool                                      | `0x8f16B5713F412C5dE4951Aaf678Eb8409101f819`  |
| Price oracle                                        | `0xE4Cd99d4698482ff263C300fbe2fA5fFE08af1622` |

**Supported assets**

| Symbol | Address                                      | Decimals |
| ------ | -------------------------------------------- | -------- |
| WETH   | `0x3439153EB7AF838Ad19d56E1571FBD09333C2809` | 18       |
| USDC   | `0x84A71ccD554Cc1b02749b35d22F684CC8ec987e1` | 6        |
| USDT   | `0x0709F39376dEEe2A2dfC94A58EdEb2Eb9DF012bD` | 6        |
| PENGU  | `0x9eBe3A824Ca958e4b3Da772D2065518F009CBa62` | 18       |

Markets are defined by `(collateralAsset, debtAsset)` pairs. Discover them dynamically via `getAllMarkets()` — never hardcode.

***

### Reading on-chain state

Every agent interaction starts with reads. These are free `eth_call` operations that require no signing and no gas.

#### Discover markets

```
getAllMarkets() → (bytes32[] keys, MarketConfig[] configs)
getMarketConfig(collateral, debt) → MarketConfig
getMarketCount() → uint256
getMaxLeverage(collateral, debt) → uint16
```

The `MarketConfig` struct contains: `enabled`, `maxLeverageBps`, `minLeverageBps`, `swapPath[]`, `reverseSwapPath[]`, `slippageToleranceBps`, `feeBps`.

#### Quote a trade

```
quoteLeverageUp(collateral, debt, amount, leverageBps, user)
  → (flashLoanAmount, estimatedTotalDebt, estimatedHealthFactor)

quoteLeverageDown(user, collateral, debt, targetLeverageBps)
  → (debtToRepay, collateralToWithdraw, estimatedHealthFactor)
```

Always quote immediately before execution. Pool state changes between blocks.

#### Inspect positions

```
getUserPosition(user, collateral, debt)
  → (totalCollateralBase, totalDebtBase, healthFactor, currentLeverageBps)
```

**Important:** `healthFactor` here is the user's **account-wide** health factor from the lending pool. If the user has multiple positions or manual supply/borrow activity, this number reflects all of it. For isolated position risk, compute from collateral value, debt value, and the reserve's liquidation threshold.

#### Check permissions

```
getRequiredDelegation(collateral, debt, amount, leverageBps)
  → requiredDelegation

checkCreditDelegation(user, debtAsset, requiredAmount)
  → (currentDelegation, isSufficient)

paused() → bool
```

***

### Executing trades

#### Open or increase leverage

```solidity
leverageUp(
  address collateralAsset,
  address debtAsset,
  uint256 collateralAmount,
  uint16  leverageBps,
  uint256 minCollateralOut   // slippage floor
)
```

#### Reduce leverage

```solidity
leverageDown(
  address collateralAsset,
  address debtAsset,
  uint256 withdrawAmount,
  uint16  targetLeverageBps,
  uint256 maxDebtRepaid       // slippage ceiling
)
```

#### Close entirely

```solidity
closeLeverage(
  address collateralAsset,
  address debtAsset,
  uint256 minCollateralBack   // slippage floor
)
```

Native ETH variants (`leverageUpETH`, `leverageDownETH`, `closeLeverageETH`) are available when WETH is the collateral.

***

### Preflight checklist

Before submitting any `leverageUp` transaction, agents must verify:

1. **`paused()` is false** — the contract has a global pause mechanism.
2. **Market is enabled** — `getMarketConfig(collateral, debt).enabled == true`.
3. **Leverage is in range** — `minLeverageBps <= leverageBps <= maxLeverageBps`.
4. **ERC20 approval** — the collateral token must have `approve(KonaLooper, collateralAmount)` or higher.
5. **Credit delegation** — the variable debt token for the debt reserve must have `approveDelegation(KonaLooper, amount)` where amount >= `getRequiredDelegation(...)`.
6. **Quote is fresh** — `quoteLeverageUp` returns current estimates; set `minCollateralOut` from this, not from a cached value.

**First-time edge case:** If the user has never supplied the collateral asset on Kona Lend before, the first loop may need a small initial supply to prime the reserve. Detect this by checking the user's kToken balance for that reserve.

***

### Units and encoding

| Field                                    | Encoding                                                                                                |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `leverageBps`, `maxLeverageBps`, etc.    | Basis points where **10,000 = 1.0x**. So `35000` = 3.5x leverage.                                       |
| Token amounts (`collateralAmount`, etc.) | Raw integers in the token's smallest unit. USDC = 6 decimals, WETH/PENGU = 18. Never assume 18.         |
| `slippageToleranceBps`, `feeBps`         | Standard basis points divided by 10,000.                                                                |
| `healthFactor`                           | 18-decimal fixed point from the lending pool. `1e18` = health factor of 1.0. Below this = liquidatable. |

***

### Events

Index these from the KonaLooper proxy address to build position history, analytics, or agent memory:

**`LeverageUp`** — Emitted when a position is opened or increased.

```
user (indexed), collateralAsset (indexed), debtAsset (indexed),
originalDeposit, totalCollateral, totalDebt, targetLeverageBps, flashLoanPremium
```

**`LeverageDown`** — Emitted when leverage is reduced.

```
user (indexed), collateralAsset (indexed), debtAsset (indexed),
collateralAmount, debtAmount, leverageBps
```

**`MarketConfigSet`** — Market parameters changed.

```
collateralAsset (indexed), debtAsset (indexed),
enabled, maxLeverageBps, minLeverageBps
```

**`FeeCollected`** — Protocol fee taken.

```
user (indexed), asset (indexed), amount
```

Additional events: `MarketEnabled`, `MarketDisabled`, `Paused`, `Unpaused`, `Upgraded`.

Standard `eth_getLogs` with topic filters is sufficient for a lightweight indexer.

***

### Error handling

The contract uses custom errors. When a transaction reverts, decode the error selector against the ABI to get a specific reason rather than retrying blindly.

| Error                                                  | Meaning                                                                                    |
| ------------------------------------------------------ | ------------------------------------------------------------------------------------------ |
| `ContractPaused`                                       | Protocol is paused, try later                                                              |
| `MarketIsDisabled` / `MarketNotConfigured`             | This market pair isn't active                                                              |
| `LeverageTooHigh` / `LeverageTooLow` / `LeverageRange` | Requested leverage outside allowed bounds                                                  |
| `InsufficientCreditDelegation`                         | User hasn't delegated enough borrow allowance (includes current vs required in error data) |
| `InsufficientBalance` / `InsufficientCollateral`       | Not enough tokens                                                                          |
| `SlippageExceeded`                                     | Price moved beyond tolerance between quote and execution                                   |
| `HealthFactorTooLow`                                   | Resulting position would be immediately liquidatable                                       |
| `InvalidOraclePrice`                                   | Oracle returned zero or stale price for an asset                                           |
| `InvalidLeverage` / `InvalidFee` / `InvalidSwapPath`   | Malformed parameters                                                                       |

***

### Agent capability tiers

| Tier        | What it does                                                                   | Keys required                          |
| ----------- | ------------------------------------------------------------------------------ | -------------------------------------- |
| **Observe** | Read markets, quote trades, monitor positions and events                       | None                                   |
| **Compose** | Build unsigned transaction calldata, compute approval steps, simulate outcomes | None                                   |
| **Execute** | Sign and broadcast transactions, handle receipts, rebalance positions          | Yes — with explicit user authorization |

Agents should default to **Observe**. Only escalate when the user has explicitly granted signing authority. Always simulate or quote immediately before any write.

***

### Full ABI

The complete KonaLooper ABI for the current deployment. Use this directly with viem, ethers, web3.py, or any ABI-compatible library.

```json
[
  {
    "type": "receive",
    "stateMutability": "payable"
  },
  {
    "type": "function",
    "name": "checkCreditDelegation",
    "inputs": [
      { "name": "user", "type": "address" },
      { "name": "debtAsset", "type": "address" },
      { "name": "requiredAmount", "type": "uint256" }
    ],
    "outputs": [
      { "name": "currentDelegation", "type": "uint256" },
      { "name": "isSufficient", "type": "bool" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "closeLeverage",
    "inputs": [
      { "name": "collateralAsset", "type": "address" },
      { "name": "debtAsset", "type": "address" },
      { "name": "minCollateralBack", "type": "uint256" }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "closeLeverageETH",
    "inputs": [
      { "name": "minCollateralBack", "type": "uint256" }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "executeOperation",
    "inputs": [
      { "name": "asset", "type": "address" },
      { "name": "amount", "type": "uint256" },
      { "name": "premium", "type": "uint256" },
      { "name": "initiator", "type": "address" },
      { "name": "params", "type": "bytes" }
    ],
    "outputs": [
      { "name": "", "type": "bool" }
    ],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "feeRecipient",
    "inputs": [],
    "outputs": [
      { "name": "", "type": "address" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "getAllMarkets",
    "inputs": [],
    "outputs": [
      { "name": "keys", "type": "bytes32[]" },
      {
        "name": "configs",
        "type": "tuple[]",
        "components": [
          { "name": "enabled", "type": "bool" },
          { "name": "maxLeverageBps", "type": "uint16" },
          { "name": "minLeverageBps", "type": "uint16" },
          { "name": "swapPath", "type": "address[]" },
          { "name": "reverseSwapPath", "type": "address[]" },
          { "name": "slippageToleranceBps", "type": "uint16" },
          { "name": "feeBps", "type": "uint16" }
        ]
      }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "getMarketConfig",
    "inputs": [
      { "name": "collateralAsset", "type": "address" },
      { "name": "debtAsset", "type": "address" }
    ],
    "outputs": [
      { "name": "enabled", "type": "bool" },
      { "name": "maxLeverageBps", "type": "uint16" },
      { "name": "minLeverageBps", "type": "uint16" },
      { "name": "swapPath", "type": "address[]" },
      { "name": "reverseSwapPath", "type": "address[]" },
      { "name": "slippageToleranceBps", "type": "uint16" },
      { "name": "feeBps", "type": "uint16" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "getMarketConfig",
    "inputs": [
      { "name": "key", "type": "bytes32" }
    ],
    "outputs": [
      {
        "name": "",
        "type": "tuple",
        "components": [
          { "name": "enabled", "type": "bool" },
          { "name": "maxLeverageBps", "type": "uint16" },
          { "name": "minLeverageBps", "type": "uint16" },
          { "name": "swapPath", "type": "address[]" },
          { "name": "reverseSwapPath", "type": "address[]" },
          { "name": "slippageToleranceBps", "type": "uint16" },
          { "name": "feeBps", "type": "uint16" }
        ]
      }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "getMarketCount",
    "inputs": [],
    "outputs": [
      { "name": "", "type": "uint256" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "getMarketKeyAt",
    "inputs": [
      { "name": "index", "type": "uint256" }
    ],
    "outputs": [
      { "name": "", "type": "bytes32" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "getMaxLeverage",
    "inputs": [
      { "name": "collateralAsset", "type": "address" },
      { "name": "debtAsset", "type": "address" }
    ],
    "outputs": [
      { "name": "", "type": "uint16" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "getRequiredDelegation",
    "inputs": [
      { "name": "collateralAsset", "type": "address" },
      { "name": "debtAsset", "type": "address" },
      { "name": "collateralAmount", "type": "uint256" },
      { "name": "leverageBps", "type": "uint16" }
    ],
    "outputs": [
      { "name": "requiredDelegation", "type": "uint256" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "getUserPosition",
    "inputs": [
      { "name": "user", "type": "address" },
      { "name": "collateralAsset", "type": "address" },
      { "name": "debtAsset", "type": "address" }
    ],
    "outputs": [
      { "name": "totalCollateralBase", "type": "uint256" },
      { "name": "totalDebtBase", "type": "uint256" },
      { "name": "healthFactor", "type": "uint256" },
      { "name": "currentLeverageBps", "type": "uint256" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "leverageDown",
    "inputs": [
      { "name": "collateralAsset", "type": "address" },
      { "name": "debtAsset", "type": "address" },
      { "name": "withdrawAmount", "type": "uint256" },
      { "name": "targetLeverageBps", "type": "uint16" },
      { "name": "maxDebtRepaid", "type": "uint256" }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "leverageDownETH",
    "inputs": [
      { "name": "withdrawAmount", "type": "uint256" },
      { "name": "targetLeverageBps", "type": "uint16" },
      { "name": "maxDebtRepaid", "type": "uint256" }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "leverageUp",
    "inputs": [
      { "name": "collateralAsset", "type": "address" },
      { "name": "debtAsset", "type": "address" },
      { "name": "collateralAmount", "type": "uint256" },
      { "name": "leverageBps", "type": "uint16" },
      { "name": "minCollateralOut", "type": "uint256" }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "type": "function",
    "name": "leverageUpETH",
    "inputs": [
      { "name": "targetLeverageBps", "type": "uint16" },
      { "name": "minCollateralOut", "type": "uint256" },
      { "name": "debtAsset", "type": "address" }
    ],
    "outputs": [],
    "stateMutability": "payable"
  },
  {
    "type": "function",
    "name": "oracle",
    "inputs": [],
    "outputs": [
      { "name": "", "type": "address" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "owner",
    "inputs": [],
    "outputs": [
      { "name": "", "type": "address" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "paused",
    "inputs": [],
    "outputs": [
      { "name": "", "type": "bool" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "pool",
    "inputs": [],
    "outputs": [
      { "name": "", "type": "address" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "quoteLeverageDown",
    "inputs": [
      { "name": "user", "type": "address" },
      { "name": "collateralAsset", "type": "address" },
      { "name": "debtAsset", "type": "address" },
      { "name": "targetLeverageBps", "type": "uint16" }
    ],
    "outputs": [
      { "name": "debtToRepay", "type": "uint256" },
      { "name": "collateralToWithdraw", "type": "uint256" },
      { "name": "estimatedHealthFactor", "type": "uint256" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "quoteLeverageUp",
    "inputs": [
      { "name": "collateralAsset", "type": "address" },
      { "name": "debtAsset", "type": "address" },
      { "name": "collateralAmount", "type": "uint256" },
      { "name": "leverageBps", "type": "uint16" },
      { "name": "user", "type": "address" }
    ],
    "outputs": [
      { "name": "flashLoanAmount", "type": "uint256" },
      { "name": "estimatedTotalDebt", "type": "uint256" },
      { "name": "estimatedHealthFactor", "type": "uint256" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "router",
    "inputs": [],
    "outputs": [
      { "name": "", "type": "address" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "weth",
    "inputs": [],
    "outputs": [
      { "name": "", "type": "address" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "function",
    "name": "usdc",
    "inputs": [],
    "outputs": [
      { "name": "", "type": "address" }
    ],
    "stateMutability": "view"
  },
  {
    "type": "event",
    "name": "LeverageUp",
    "inputs": [
      { "name": "user", "type": "address", "indexed": true },
      { "name": "collateralAsset", "type": "address", "indexed": true },
      { "name": "debtAsset", "type": "address", "indexed": true },
      { "name": "originalDeposit", "type": "uint256", "indexed": false },
      { "name": "totalCollateral", "type": "uint256", "indexed": false },
      { "name": "totalDebt", "type": "uint256", "indexed": false },
      { "name": "targetLeverageBps", "type": "uint16", "indexed": false },
      { "name": "flashLoanPremium", "type": "uint256", "indexed": false }
    ]
  },
  {
    "type": "event",
    "name": "LeverageDown",
    "inputs": [
      { "name": "user", "type": "address", "indexed": true },
      { "name": "collateralAsset", "type": "address", "indexed": true },
      { "name": "debtAsset", "type": "address", "indexed": true },
      { "name": "collateralAmount", "type": "uint256", "indexed": false },
      { "name": "debtAmount", "type": "uint256", "indexed": false },
      { "name": "leverageBps", "type": "uint16", "indexed": false }
    ]
  },
  {
    "type": "event",
    "name": "FeeCollected",
    "inputs": [
      { "name": "user", "type": "address", "indexed": true },
      { "name": "asset", "type": "address", "indexed": true },
      { "name": "amount", "type": "uint256", "indexed": false }
    ]
  },
  {
    "type": "event",
    "name": "MarketConfigSet",
    "inputs": [
      { "name": "collateralAsset", "type": "address", "indexed": true },
      { "name": "debtAsset", "type": "address", "indexed": true },
      { "name": "enabled", "type": "bool", "indexed": false },
      { "name": "maxLeverageBps", "type": "uint16", "indexed": false },
      { "name": "minLeverageBps", "type": "uint16", "indexed": false }
    ]
  },
  {
    "type": "event",
    "name": "MarketEnabled",
    "inputs": [
      { "name": "collateralAsset", "type": "address", "indexed": true },
      { "name": "debtAsset", "type": "address", "indexed": true }
    ]
  },
  {
    "type": "event",
    "name": "MarketDisabled",
    "inputs": [
      { "name": "collateralAsset", "type": "address", "indexed": true },
      { "name": "debtAsset", "type": "address", "indexed": true }
    ]
  },
  {
    "type": "event",
    "name": "Paused",
    "inputs": []
  },
  {
    "type": "event",
    "name": "Unpaused",
    "inputs": []
  },
  {
    "type": "event",
    "name": "Upgraded",
    "inputs": [
      { "name": "implementation", "type": "address", "indexed": true }
    ]
  },
  {
    "type": "error",
    "name": "AssetMismatch",
    "inputs": []
  },
  {
    "type": "error",
    "name": "ContractPaused",
    "inputs": []
  },
  {
    "type": "error",
    "name": "HealthFactorTooLow",
    "inputs": []
  },
  {
    "type": "error",
    "name": "InsufficientBalance",
    "inputs": []
  },
  {
    "type": "error",
    "name": "InsufficientCollateral",
    "inputs": []
  },
  {
    "type": "error",
    "name": "InsufficientCreditDelegation",
    "inputs": [
      { "name": "currentDelegation", "type": "uint256" },
      { "name": "requiredDelegation", "type": "uint256" }
    ]
  },
  {
    "type": "error",
    "name": "InvalidLeverage",
    "inputs": []
  },
  {
    "type": "error",
    "name": "InvalidOraclePrice",
    "inputs": [
      { "name": "asset", "type": "address" }
    ]
  },
  {
    "type": "error",
    "name": "LeverageRange",
    "inputs": []
  },
  {
    "type": "error",
    "name": "LeverageTooHigh",
    "inputs": []
  },
  {
    "type": "error",
    "name": "LeverageTooLow",
    "inputs": []
  },
  {
    "type": "error",
    "name": "MarketIsDisabled",
    "inputs": []
  },
  {
    "type": "error",
    "name": "MarketNotConfigured",
    "inputs": []
  },
  {
    "type": "error",
    "name": "MarketNotFound",
    "inputs": []
  },
  {
    "type": "error",
    "name": "MaxLeverageExceedsLTV",
    "inputs": [
      { "name": "maxLeverageBps", "type": "uint256" },
      { "name": "maxSafeLeverageBps", "type": "uint256" }
    ]
  },
  {
    "type": "error",
    "name": "SlippageExceeded",
    "inputs": []
  },
  {
    "type": "error",
    "name": "ZeroAddress",
    "inputs": []
  },
  {
    "type": "error",
    "name": "ZeroAmount",
    "inputs": []
  }
]
```

***

### Integration checklist

Use this before shipping any agent, bot, or automation against KonaLooper.

* [ ] All calls target the **proxy** address, never the implementation
* [ ] Markets and leverage caps come from `getMarketConfig`, not assumptions
* [ ] Token amounts use the **correct decimals per asset** (6 for stables, 18 for others)
* [ ] Health factor context is communicated clearly (account-wide, not per-position)
* [ ] Quotes are refreshed within the same block window as execution
* [ ] `paused()` is checked before every write
* [ ] Custom errors are decoded and surfaced, not swallowed
* [ ] Credit delegation is verified or set before `leverageUp`
* [ ] If the proxy emits `Upgraded`, the ABI is re-fetched and validated

***

### Getting started

The fastest path to a working agent:

1. Point viem, ethers, or web3.py at Abstract RPC with the ABI above
2. Call `getAllMarkets()` to see what's available
3. Call `quoteLeverageUp(...)` with a test amount to understand the output shape
4. Index `LeverageUp` events from the proxy to see real positions being opened
5. Build from there

Everything is on-chain. No API keys, no rate limits, no accounts to create. Just a contract and a node.
