# Oracle

Lombard is introducing two changes relevant to oracle integrations:

1. **LBTC** [**becomes yield-bearing on July 22**](https://docs.google.com/document/d/1aCcZACyAI4hpm6iPpzvvGcZOSQzxFVd2DxcA-2zr-HY/edit?usp=sharing)**.** The price of LBTC will accumulate over Bitcoin based on yield earned.
2. **BTC.b launch.** A new yieldless, risk-free Bitcoin wrapper token.

Both tokens are minted on Lombard Ledger (the appchain powering the Lombard ecosystem) and bridged via burn-and-mint mechanisms. Two Proof of Reserve feeds are required, one for each asset, with LBTC building on top of BTC.b.

> **Note:** The steps below include testnet URLs. See [API URLs](https://claude.ai/chat/73424983-8063-4c79-a827-bd15373abb69#api-urls) at the end of this document for production endpoints.

***

### Step 1: BTC.b (Lombard Protocol Solvency)

The supply of BTC backing Lombard Protocol compared to BTC represented on Lombard Ledger.

**Calculate `btcReserves`:**

BTC supply can be calculated and verified based on all Lombard Protocol BTC addresses. All Lombard Protocol BTC addresses are published on the Base network.

* Contract address: <https://basescan.org/address/0xe7Ebc588F4EC9297d9867aD75a9b5D86848c8018>
* Verification examples in Golang: <https://github.com/lombard-finance/verifier> (send IDs for access)

**Calculate `btcSupply`:**

Retrieve from Lombard Ledger:

```
GET https://ledger-gastald.lombard-fi.com:1317/lombard-finance/ledger/assets/total_supply/ucbtc
```

Returns a JSON object with a `value` field.

**Calculate the ratio:**

```
ratio = btcReserves / btcSupply
```

* Any ratio value **> 1.0** should be clipped to 1.0 for reporting purposes, to prove the statement that the protocol is fully solvent.
* Any ratio value **< 1.0** should trigger secondary checks where possible before publishing. Alerts should be in place given the critical impact on DeFi activity (i.e. liquidations) from inaccurate reporting. Monitoring and incident response plan/escalation procedure between teams should be implemented.

***

### Step 2: LBTC Ratio (LBTC/BTC)

Can be combined with Step 1 for completeness.

#### Option A: Calculate via Supply

**Retrieve `lbtcSupply`** from Lombard Ledger:

```
GET https://ledger-gastald.lombard-fi.com:1317/lombard-finance/ledger/assets/total_supply/uclbtc
```

**Retrieve `btcBackingLBTC`** from Lombard Ledger:

```
GET https://ledger-gastald.lombard-fi.com:1317/lombard-finance/ledger/btcstaking/staking_vault_base_balance
```

**Calculate:**

```
ratio = lbtcSupply / btcBackingLBTC
```

#### Option B: Use Ratio Directly

Get the ratio directly from Lombard Ledger's LBTC vault view function:

```
GET https://ledger-gastald.lombard-fi.com:1317/lombard-finance/ledger/btcstaking/current_ratio/uclbtc
```

If needed, calculate the inverse: `rate = 1 / ratio`.

**Interpreting the value:**

* Any value **> 1.0** shows that LBTC has gained value relative to BTC.
* Any value **< 1.0** shows that LBTC has lost value relative to BTC. Implement secondary checks where possible before publishing. Alerts should be in place given the critical impact on DeFi activity (i.e. liquidations) from inaccurate reporting. Monitoring and incident response plan/escalation procedure should be provided.

***

### Step 3: BTC.b Ratio

#### Option A: From Lombard Ledger and Destination Chains

```
ratio = (btcSupply - btcBackingLBTC) / BTC.bDestinationChainsSupply
```

#### Option B: From Bitcoin Network, Lombard Ledger and Destination Chains

```
ratio = (btcReserves - (lbtcSupply * lbtcRatio)) / BTC.bDestinationChainsSupply
```

***

### API URLs

| Environment                | URL                                          | Networks                         |
| -------------------------- | -------------------------------------------- | -------------------------------- |
| Testnet                    | `https://ledger-gastald.lombard-fi.com:1317` | Bitcoin Signet, Ethereum Holesky |
| Production (load balanced) | `https://ledger-mainnet.lombard-fi.com:1317` | Mainnet                          |

#### Query Data at a Specific Block

```bash
curl -H "x-cosmos-block-height: 6256072" \
  "https://ledger-mainnet.lombard-fi.com:1317/lombard-finance/ledger/btcstaking/staking_vault_base_balance"
```

```bash
curl -s -H "x-cosmos-block-height: 6256072" \
  "https://ledger-mainnet.lombard-fi.com:1317/lombard-finance/ledger/assets/total_supply/ucbtc" | jq .
```

#### Resolve Block at a Specific Timestamp

Function to get a Cosmos block height at a specific timestamp via binary search on Tendermint RPC:

```typescript
export async function getCosmosBlockAtTimestamp(
  rpcUrl: string,
  targetTimestamp: number
): Promise<number> {
  // Get latest block height
  const statusRes = await axios.get(`${rpcUrl}/status`);
  const latestHeight = parseInt(statusRes.data.result.sync_info.latest_block_height);

  // Check if target is in the future
  const latestBlockRes = await axios.get(`${rpcUrl}/block?height=${latestHeight}`);
  const latestTime = new Date(latestBlockRes.data.result.block.header.time).getTime() / 1000;
  if (targetTimestamp >= latestTime) {
    console.log(`Cosmos: target timestamp is at or after latest block, using height ${latestHeight}`);
    return latestHeight;
  }

  let low = 1;
  let high = latestHeight;
  let bestHeight = latestHeight;
  let bestTimeDiff = Number.MAX_SAFE_INTEGER;

  while (high - low > 1) {
    const mid = Math.floor((low + high) / 2);
    try {
      const blockRes = await axios.get(`${rpcUrl}/block?height=${mid}`);
      const blockTime = new Date(blockRes.data.result.block.header.time).getTime() / 1000;
      const timeDiff = Math.abs(blockTime - targetTimestamp);

      if (timeDiff < bestTimeDiff) {
        bestTimeDiff = timeDiff;
        bestHeight = mid;
      }

      if (blockTime < targetTimestamp) {
        low = mid;
      } else {
        high = mid;
      }
    } catch (error) {
      console.error(`Error fetching Cosmos block ${mid}:`, error);
      high = mid - 1;
    }
  }

  console.log(`Cosmos: Found block ${bestHeight} for timestamp ${targetTimestamp}`);
  return bestHeight;
}
```
