# Hock: borrow HYPE against Elysium tokens

Hock is a fixed-term lending protocol on Elysium (chain id 99901). A wallet locks a token it holds and receives HYPE at once, for one fee and one date. There are no liquidations: nothing can close the loan before its date, whatever the price does. Repay the loan by the date and the tokens come back. If it is not repaid in time, the vault keeps the tokens and nothing else is owed.

This file tells an agent how to check a market, get a quote, borrow, and repay, using its own wallet. Hock never holds your keys; every action is a transaction your wallet signs.

Site: https://hock.markets · Docs: https://hock.markets/docs · X: https://x.com/hockmarkets

## Two ways to connect

- **MCP server (easiest).** Add `https://hock.markets/mcp` as a Streamable HTTP MCP server. No key. For example: `claude mcp add --transport http hock https://hock.markets/mcp`. Tools: `protocol_info`, `list_markets`, `quote_loan`, `get_loans`, and `build_price_check`, `build_approve`, `build_borrow`, `build_repay`, which return an unsigned transaction (`chainId`, `to`, `data`, `value` in wei) for your wallet to sign and send. The server never signs anything.
- **Direct contract calls**, described below, with any library or `cast`.

## Rules for the agent

1. **Borrow, repay or deposit only when your owner asks you to.** Reading markets and quotes is always fine.
2. **Before borrowing, tell your owner the terms in plain words**: tokens locked, HYPE received, HYPE to repay, and the exact date and time it is due. Wait for a yes.
3. **Never let a loan expire by accident.** Expiry is final: the tokens go to the vault. Track every loan's `expiry` and remind your owner well before it (a day before for 7 and 14 day loans, a few hours before for 1 and 3 day loans). Repay before the date unless your owner has told you to let it go.
4. Keep a little HYPE for gas. Never send more than the loan's exact `principal` when repaying.
5. Hock is new and unaudited. Treat it as experimental and don't borrow against tokens your owner can't afford to lose.

## Network

| | |
|---|---|
| Chain | Elysium, chain id `99901`, gas in HYPE |
| RPC | `https://rpc.elysium.kinetiq.xyz` (official), or `https://rpc.agoradex.app` as a backup |
| Explorer | `https://explorer.volta.family` |
| ABIs | `https://hock.markets/abi/HockCore.json`, `https://hock.markets/abi/HockVault.json` |

## Contracts

Hock has one deployment per pool engine (v4 PoolManager). Use the core and vault that belong to your token.

**Uniswap v4 engine** (Volta, Ascend, Montra launches)
- Core: `0xbFE23356e705D2c2eD512972E40fF0DF5eD2E1C8`
- Vault: `0x141E0d88eD0C52700eeF5eb8C64265f4aa25cd94`

**ElysPump engine**
- Core: `0xE055B1827BDf6912E8071A9F65703C4d9e63C5b5`
- Vault: `0xA20DC61e529F1F0f750343084171230C3f7fdea9`

**Kleos engine**
- Core: `0xff667023d6702bd0A8d4a89AbeFCc4a7d9C92D30`
- Vault: `0xFD43E7a558fB097a00349e0D66Bf4A265C1C0891`

**Listed tokens**

| Token | Address | Core / vault |
|---|---|---|
| VOLTA | `0x0f79931689Af199e7CF868ed1107bBA2C83c68f7` | Uniswap v4 |
| YIELDEX | `0x301eB259De132D592966fe0712DB75b27792A68a` | Uniswap v4 |
| VOID | `0xD31B21Cb80E431AC996269deC31A40fCf048B77f` | Uniswap v4 |
| ETF | `0x3B050A7C1039FEF56e9c241608953D6E6d5c1D9E` | Uniswap v4 |
| e/acc | `0x8df4f39d592de2aAee15838B265C2392d19A4128` | Uniswap v4 |
| EACCAT | `0x32193Afd14c53f12c45A4c04ECA9F7Ba98e3ec71` | Uniswap v4 |
| A/ACC | `0xAACC5bc6EA24CB753E5C2D48C88f7e361a50AACC` | Uniswap v4 |
| CHAMELEON | `0xd662D66eC991A3eae4EcBdA34327264c53d4cF38` | Uniswap v4 |
| HOCK | `0x4Bb51327Eb190aBE8372215dcfb1CE0B46837A1d` | Uniswap v4 (lent against by project vaults) |
| BLOB | `0x9a9815Af521149E8D982791703A31bca2F95f534` | ElysPump |
| AGORA | `0x5e5Df82d563FCF36b6f853c4D09f89e2d18825B4` | Kleos |

The list grows. The current list is always on-chain: `tokens()` on each core returns every listed token. A token not on these lists can't be borrowed against.

## Terms and fees

`term` is an index: `0` = 1 day, `1` = 3 days, `2` = 7 days, `3` = 14 days. The fee is taken from the loan up front: 1%, 2.5%, 5% or 9% of the loan respectively (read the live value with `termFeeBps(term)` on the vault). You receive the loan minus the fee, and you repay the full loan. Repaying early does not refund the fee.

The loan is sized on what your tokens would actually sell for in their own pool right now, not a chart price, times the vault's loan-to-value for that token (40% or 50% today).

## How to borrow

All amounts are in wei (18 decimals). Examples use Foundry's `cast`; any library works the same way (viem, ethers, web3.py).

```sh
RPC=https://rpc.elysium.kinetiq.xyz
CORE=0xbFE23356e705D2c2eD512972E40fF0DF5eD2E1C8      # pick the core for your token
VAULT=0x141E0d88eD0C52700eeF5eb8C64265f4aa25cd94     # and its vault
TOKEN=0x8df4f39d592de2aAee15838B265C2392d19A4128      # e/acc, for example
AMOUNT=100000000000000000000000                       # tokens to lock, in wei
TERM=2                                                # 7 days
```

**1. Check the vault can lend.**

```sh
cast call $VAULT "policy(address)(bool,uint16,uint128)" $TOKEN --rpc-url $RPC   # enabled, LTV in bps, total limit
cast call $VAULT "idle()(uint256)" --rpc-url $RPC                                 # HYPE free to lend right now
```

**2. Get a quote.** `quoteBorrow` is called with `eth_call` (it simulates a sale, so it isn't marked `view`):

```sh
cast call $CORE "quoteBorrow(address,address,uint256,uint8)((uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256))" \
  $VAULT $TOKEN $AMOUNT $TERM --rpc-url $RPC
# returns (saleValue, liveValue, maxPrincipal, fee, net, ltvBps, feeBps, ratio)
#   maxPrincipal = the loan, and what you repay
#   net          = HYPE you receive now (maxPrincipal - fee)
```

If the quote reverts with **`NoReference`**, the token needs a price check: Hock compares the pool's live price with a recent snapshot so nobody can pump a pool and borrow against it in one go. Anyone can take the snapshot:

```sh
cast send $CORE "poke(address)" $TOKEN --rpc-url $RPC --private-key $KEY
# then wait at least 61 seconds; the snapshot counts from 60s to 30 minutes old
```

If it reverts with **`PriceMoving`**, the price jumped in the last minute: wait and try again. If `net` is more than the vault's `idle()`, borrow less.

**3. Approve the core to take the tokens.**

```sh
cast send $TOKEN "approve(address,uint256)" $CORE $AMOUNT --rpc-url $RPC --private-key $KEY
```

**4. Borrow.** `principal = 0` borrows the maximum. `minReceive` protects you if the price moves before the transaction lands (2% below the quoted `net` is sensible). `deadline` is a unix time after which the transaction fails.

```sh
NET=<net from the quote>
MIN=$(( NET * 98 / 100 ))
DEADLINE=$(( $(date +%s) + 600 ))
cast send $CORE "borrow(address,address,uint256,uint8,uint256,uint256,uint256)(uint256)" \
  $VAULT $TOKEN $AMOUNT $TERM 0 $MIN $DEADLINE --rpc-url $RPC --private-key $KEY
```

The HYPE arrives in your wallet in the same transaction. Elysium includes transactions about a minute after they are sent. The receipt has a `Borrowed(uint256 indexed id, address indexed borrower, address indexed vault, address token, uint256 collateral, uint256 principal, uint256 fee, uint256 expiry)` event: **store the `id` and the `expiry`.**

## How to repay

```sh
ID=<loan id>
cast call $CORE "loan(uint256)((address,uint64,uint8,uint8,address,uint64,address,uint128,uint128,uint256))" $ID --rpc-url $RPC
# (borrower, opened, term, state, vault, expiry, token, principal, fee, collateral)
# state: 1 = active, 2 = repaid, 3 = expired and settled

cast send $CORE "repay(uint256)" $ID --value <principal> --rpc-url $RPC --private-key $KEY
```

Send exactly `principal` in HYPE (any other amount reverts with `WrongAmount`). Repay strictly before `expiry`: at or after it, `repay` reverts with `Expired`, and anyone can call `settle(id)` to hand the tokens to the vault. The tokens return to the borrower in the same transaction as the repayment. Anyone can repay a loan on the borrower's behalf; the tokens always go back to the borrower.

To find all of a wallet's loans without event logs, read `loan(id)` for every id from 1 to `nextLoanId() - 1` on each core and keep those whose `borrower` is the wallet. Public Elysium RPCs only serve 10,000 blocks of logs per request.

## Lending

Vaults are ERC-4626 vaults of wrapped HYPE. Deposit native HYPE with `depositNative(address to)` (send HYPE as the value; plain transfers to the vault are refused) and withdraw with `redeemNative(uint256 shares, address to, address owner)`. Only HYPE not currently lent out can be withdrawn (`maxWithdraw(owner)`). Lenders earn every loan fee; if a loan expires unpaid, the vault keeps its collateral, which may be worth less than the loan.

## Staking $HOCK

`HockStaking` at `0xbe31F5305167EE3cF2801d384160161AaEBc9aD5` pays $HOCK stakers Hock's 10% share of every loan fee, in HYPE, streamed over seven days. `stake(amount)` after approving $HOCK, `unstake(amount)`, `claim()` and `exit()`; `earned(wallet)` is what can be claimed now. No lockup and no owner.

## Project vaults

Anyone can open a vault for a listed token with `HockVaultLauncher.launch(name, symbol, depositCap, termFeeBps[4], policies[])`, sending the first deposit as the value. The vault is owned by the sender. Launchers: Uniswap v4 `0x8a1Fa5B86bd7ad9a5F5aB6DC1e5B4f4DC16CA9e6`, ElysPump `0xB383833F2d075F1548376640fB5d5B748075E196`, Kleos `0xE8d7f04F2FaA7b83b9C551a1112Aa61081A9AB36`. A core's `vaults()` returns every vault; quote each one and borrow from the best that has the HYPE free.

## Errors, in plain words

Tools like `cast` often show a revert as its 4-byte code; match it here.

| Error | Code | Meaning |
|---|---|---|
| `NoReference` | `0x46b4f71d` | Run a price check (`poke`), wait a minute, quote again. |
| `PriceMoving` | `0xe22f0465` | The price moved sharply in the last minute. Wait and retry. |
| `TokenOff` / `NotListed` | `0x4b54de52` / `0x665c1c57` | This vault doesn't lend against this token. |
| `TermOff` | `0xaa3d8ab2` | That term isn't offered for this token. |
| `TooMuch` | `0xe0f0d3cc` | Asking for more than the vault will lend against this amount. |
| `TooLittle` | `0x5cfa1edd` | The price moved and you would receive less than `minReceive`. |
| `BorrowPaused` | `0x12b0cb46` | Borrowing is paused. Repaying always works. |
| `Expired` | `0x203d82d8` | When repaying: the loan has passed its date and can no longer be repaid. When borrowing: the `deadline` passed before the transaction landed; send it again. |
| `WrongAmount` | `0x49986e73` | Repay with exactly the loan's `principal`. |
