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

# Sarcophagus

> Technical specification and searcher integration guide for the permissionless r33-for-protocol-fees mechanism on Robinhood Chain.

Sarcophagus is a permissionless, fixed-cost mechanism for exchanging **r33** for ERC-20 protocol fees accumulated by the contract. A successful caller sends the current r33 threshold directly to the dead address and receives the Sarcophagus's entire balance of every selected fee token.

<CardGroup cols={2}>
  <Card title="Permissionless execution" icon="users">
    Any address can call `bury` with a valid nonce, token list, minimum outputs, r33 balance, and allowance.
  </Card>

  <Card title="Atomic settlement" icon="shield-check">
    The r33 payment and every selected token transfer succeed together or the whole transaction reverts.
  </Card>

  <Card title="Fixed on-chain cost" icon="badge-dollar-sign">
    There is no oracle or auction curve. The owner-configured r33 threshold is the contract's only exchange price.
  </Card>

  <Card title="Searcher-directed claims" icon="scan-search">
    Callers choose which ERC-20 balances to claim, up to the current `maxTokenClaim` value.
  </Card>
</CardGroup>

<Warning title="Deployment is not the same as an available claim">
  The Robinhood contract is deployed and verified. A viable claim exists only after ERC-20 fees have reached it and their realizable value exceeds the r33 cost, gas, slippage, and execution risk. Fee routing and balances must be checked live.
</Warning>

## Robinhood deployment

The following values were read at Robinhood block `38,278,392` on **August 16, 2026**. Mutable values can change after this block.

| Field                    | Value                                                                                                        |
| ------------------------ | ------------------------------------------------------------------------------------------------------------ |
| Network                  | Robinhood Chain                                                                                              |
| Chain ID                 | `4663`                                                                                                       |
| Public RPC               | `https://rpc.mainnet.chain.robinhood.com`                                                                    |
| Sarcophagus              | [`0x7125...Aba3e`](https://robinhoodchain.blockscout.com/address/0x712567e71a93Fb111510A790cAf3469677aAba3e) |
| r33                      | [`0x4e51...0FeeE`](https://robinhoodchain.blockscout.com/address/0x4e5195469A0360f5dfe811730C9CCaCFF0a0FeeE) |
| r33 token metadata       | `xRAM Liquid Staking Token` / `r33` / 18 decimals                                                            |
| Owner                    | [`0x20D6...BE1A`](https://robinhoodchain.blockscout.com/address/0x20D630cF1f5628285BfB91DfaC8C89eB9087BE1A)  |
| r33 threshold            | `3,333 r33` (`3_333e18` raw units)                                                                           |
| Maximum tokens per claim | `100`                                                                                                        |
| Nonce                    | `1`                                                                                                          |
| r33 destination          | [`0x0000...dEaD`](https://robinhoodchain.blockscout.com/address/0x000000000000000000000000000000000000dEaD)  |

```text Canonical addresses theme={null}
SARCOPHAGUS=0x712567e71a93Fb111510A790cAf3469677aAba3e
R33_TOKEN=0x4e5195469A0360f5dfe811730C9CCaCFF0a0FeeE
OWNER=0x20D630cF1f5628285BfB91DfaC8C89eB9087BE1A
R33_DEAD_ADDRESS=0x000000000000000000000000000000000000dEaD
```

<Note title="Read mutable state before every submission">
  `exchangeAmountThreshold`, `maxTokenClaim`, `nonce`, token balances, and the caller's r33 allowance are execution inputs—not constants. Read them at one block, build the call, and simulate the exact transaction against current state.
</Note>

## Execution flow

```mermaid theme={null}
flowchart LR
    A["Protocol fee sources"] -->|"ERC-20 fees"| B["Sarcophagus balances"]
    S["Searcher"] -->|"read nonce, threshold, limits, balances"| B
    S -->|"approve r33"| R["r33 token"]
    S -->|"bury(nonce, tokens, minimums)"| B
    R -->|"exact threshold"| D["0x...dEaD"]
    B -->|"full selected balances"| S
```

`bury` is an atomic **first-valid-transaction** race. It is not a Dutch auction, sealed-bid auction, or oracle-priced swap. The first included transaction that satisfies every check consumes the current nonce and claims the selected balances.

<Steps>
  <Step title="Validate the call shape">
    The token list must be non-empty, no longer than `maxTokenClaim`, and the same length as the minimum-output array.
  </Step>

  <Step title="Consume the expected nonce">
    The supplied nonce must equal `nonce()`. The contract increments it for the successful claim. A later revert rolls the increment back with the rest of the transaction.
  </Step>

  <Step title="Send the r33 threshold">
    `safeTransferFrom` moves exactly `exchangeAmountThreshold` r33 from the caller directly to `0x000...dEaD`.
  </Step>

  <Step title="Sweep selected fee assets">
    For each selected token, the contract reads its complete Sarcophagus balance, checks it against the paired minimum, and transfers that full balance to the caller.
  </Step>

  <Step title="Emit the receipt">
    A successful call emits `Buried(nonce, user, tokensClaimed)` using the nonce supplied by the caller.
  </Step>
</Steps>

<Note title="r33 is transferred to the dead address">
  This Robinhood deployment sends r33 to `0x000...dEaD`; it does not call an r33 `burn` function. The transfer removes the tokens from ordinary circulation but does not reduce the ERC-20 `totalSupply` value.
</Note>

## Searcher runbook

### 1. Discover candidate fee assets

Sarcophagus does **not** maintain an enumerable token registry. Searchers must discover candidates from trusted Ramses fee-source configuration, ERC-20 `Transfer` logs into the contract, or another independently maintained index.

Treat discovery as untrusted input:

* Confirm every candidate is the intended token contract on chain `4663`.
* Read `balanceOf(Sarcophagus)` at the same pinned block used for the other quote inputs.
* Exclude zero balances and tokens with incompatible or reverting ERC-20 behavior.
* Deduplicate token addresses before constructing the call.
* Do not assume the contract holds only assets shown by a block explorer UI.

### 2. Price the opportunity

For candidate tokens (T\_i), a claim is economically attractive only when the expected realizable output exceeds all costs:

$$
\sum_i \operatorname{value}(balance_i) > \operatorname{value}(r33Threshold) + gas + slippage + risk
$$

The contract does not calculate this inequality and does not validate token prices. Searchers are responsible for pricing, liquidity checks, gas estimation, and downstream execution.

### 3. Set minimum outputs

`_minAmountsOut[i]` is compared with the **raw Sarcophagus balance** of `_tokens[i]`. It is not a price, quote, or decimal-normalized value.

Use minimums to protect against another transaction reducing a selected balance before inclusion. Setting every minimum to zero removes that protection and can allow the call to pay r33 while receiving no value from one or more selected tokens.

### 4. Approve and simulate

The caller needs at least the threshold amount of r33 and sufficient allowance for Sarcophagus. Approval is made on the r33 token; r33 should not be transferred to Sarcophagus manually.

Simulate the exact `bury` call from the intended sender immediately before submission. A successful simulation is only a point-in-time result: another claim or owner update can still make the pending transaction revert.

### 5. Submit competitively

Public-mempool transactions reveal the selected assets and minimums. Another searcher can independently submit a valid claim with the same nonce if it has r33 and allowance. The contract does not reserve an opportunity for the first observer.

After inclusion, verify the transaction status and `Buried` event rather than inferring success from submission alone.

## TypeScript example

This `viem` example pins quote reads to one block, applies a 0.5% balance buffer, checks allowance, and simulates the exact call. Candidate-token discovery and economic pricing are intentionally separate.

```ts theme={null}
import { createPublicClient, createWalletClient, http, parseAbi } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'

const robinhood = {
  id: 4663,
  name: 'Robinhood Chain',
  nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
  rpcUrls: {
    default: { http: ['https://rpc.mainnet.chain.robinhood.com'] },
  },
} as const

const SARCOPHAGUS = '0x712567e71a93Fb111510A790cAf3469677aAba3e'

const sarcophagusAbi = parseAbi([
  'function R33() view returns (address)',
  'function nonce() view returns (uint256)',
  'function exchangeAmountThreshold() view returns (uint256)',
  'function maxTokenClaim() view returns (uint256)',
  'function bury(uint256 nonce, address[] tokens, uint256[] minAmountsOut)',
])

const erc20Abi = parseAbi([
  'function balanceOf(address) view returns (uint256)',
  'function allowance(address,address) view returns (uint256)',
])

const publicClient = createPublicClient({
  chain: robinhood,
  transport: http(),
})

const account = privateKeyToAccount(process.env.SEARCHER_KEY as `0x${string}`)
const walletClient = createWalletClient({
  account,
  chain: robinhood,
  transport: http(),
})

// Supply addresses discovered from trusted fee configuration or indexed logs.
const tokens: readonly `0x${string}`[] = [
  // '0x...',
]

const blockNumber = await publicClient.getBlockNumber()
const read = { address: SARCOPHAGUS, abi: sarcophagusAbi, blockNumber } as const

const [r33, nonce, threshold, maxTokenClaim] = await Promise.all([
  publicClient.readContract({ ...read, functionName: 'R33' }),
  publicClient.readContract({ ...read, functionName: 'nonce' }),
  publicClient.readContract({ ...read, functionName: 'exchangeAmountThreshold' }),
  publicClient.readContract({ ...read, functionName: 'maxTokenClaim' }),
])

if (tokens.length === 0 || BigInt(tokens.length) > maxTokenClaim) {
  throw new Error('Invalid token count')
}

const balances = await Promise.all(
  tokens.map((token) =>
    publicClient.readContract({
      address: token,
      abi: erc20Abi,
      functionName: 'balanceOf',
      args: [SARCOPHAGUS],
      blockNumber,
    }),
  ),
)

// Raw token units. Choose policy based on each token's behavior and latency.
const minAmountsOut = balances.map((balance) => (balance * 995n) / 1000n)

const allowance = await publicClient.readContract({
  address: r33,
  abi: erc20Abi,
  functionName: 'allowance',
  args: [account.address, SARCOPHAGUS],
})

if (allowance < threshold) {
  throw new Error('Approve the r33 threshold, then rebuild the quote from a new block')
}

const { request } = await publicClient.simulateContract({
  account,
  address: SARCOPHAGUS,
  abi: sarcophagusAbi,
  functionName: 'bury',
  args: [nonce, [...tokens], minAmountsOut],
})

// Re-evaluate profitability and freshness before signing.
const hash = await walletClient.writeContract(request)
const receipt = await publicClient.waitForTransactionReceipt({ hash })
if (receipt.status !== 'success') throw new Error(`bury reverted: ${hash}`)
```

<Warning title="Key management">
  The example uses an environment variable only to keep the transaction flow concise. Production searchers should use an appropriate signer, isolated key policy, transaction replacement strategy, and private-orderflow decision for their operating environment.
</Warning>

## Contract interface

### State reads

| Function                    | Mutability     | Meaning                                                          |
| --------------------------- | -------------- | ---------------------------------------------------------------- |
| `R33()`                     | immutable view | r33 ERC-20 charged for every successful claim                    |
| `exchangeAmountThreshold()` | view           | Exact raw r33 amount transferred by `bury`                       |
| `maxTokenClaim()`           | view           | Maximum number of token entries accepted by one call             |
| `nonce()`                   | view           | Nonce required by the next successful claim                      |
| `owner()`                   | view           | Address authorized to update parameters and rescue ERC-20 tokens |

### `bury`

```solidity theme={null}
function bury(
    uint256 _nonce,
    address[] calldata _tokens,
    uint256[] calldata _minAmountsOut
) external
```

| Parameter        | Type        | Requirement                                                          |
| ---------------- | ----------- | -------------------------------------------------------------------- |
| `_nonce`         | `uint256`   | Must equal the current `nonce()`                                     |
| `_tokens`        | `address[]` | Non-empty; length must not exceed `maxTokenClaim()`                  |
| `_minAmountsOut` | `uint256[]` | Same length and index order as `_tokens`; values are raw token units |

The function is `nonReentrant`. On success it transfers the r33 threshold from `msg.sender` to the dead address, then transfers the complete pre-transfer Sarcophagus balance of each selected token to `msg.sender`.

### Owner functions

```solidity theme={null}
function rescue(address token, address to, uint256 amount) external onlyOwner
function setExchangeAmountThreshold(uint256 threshold) external onlyOwner
function setMaxTokenClaim(uint256 maxTokenClaim) external onlyOwner
```

* `rescue` can move any ERC-20 balance from the contract at any time.
* The threshold and maximum claim count must each remain greater than zero.
* Parameter setters do not emit dedicated events in this deployment. Track owner transactions and confirm storage directly.

## Events and errors

### `Buried`

```solidity theme={null}
event Buried(
    uint256 indexed nonce,
    address indexed user,
    address[] tokensClaimed
)
```

The event records the consumed nonce, successful caller, and requested token-address array. It does not include transferred amounts; reconstruct amounts from transaction traces, ERC-20 `Transfer` logs, or pre-transaction state.

### Custom errors

| Error                | Trigger                                               |
| -------------------- | ----------------------------------------------------- |
| `InvalidNonce()`     | Supplied nonce differs from `nonce()`                 |
| `NoTokensProvided()` | Token array is empty                                  |
| `TooManyAssets()`    | Token count exceeds `maxTokenClaim()`                 |
| `LengthMismatch()`   | Token and minimum-output array lengths differ         |
| `SlippageExceeded()` | A selected balance is below its paired minimum        |
| `InvalidThreshold()` | Owner attempts to set the threshold to zero           |
| `InvalidMaxClaim()`  | Owner attempts to set the maximum claim count to zero |

ERC-20 calls can also revert with token-specific errors or `SafeERC20` failures.

## Atomicity and token behavior

<AccordionGroup>
  <Accordion title="What if one selected token fails?">
    The entire transaction reverts, including the r33 transfer and nonce increment. A malformed or incompatible token therefore blocks only batches that include it; retry without that token.
  </Accordion>

  <Accordion title="What happens with duplicate token addresses?">
    The first occurrence can transfer the token's full balance. A later occurrence observes the remaining balance, normally zero. A positive minimum on the duplicate reverts the entire call; a zero minimum adds no value and wastes gas.
  </Accordion>

  <Accordion title="Are fee-on-transfer or rebasing tokens fully protected by minimums?">
    No. The minimum is checked against `balanceOf(Sarcophagus)` before transfer, not the caller's received amount. A transfer-tax token can deliver less than its checked balance, and unusual rebasing or callback behavior may cause different results or a revert.
  </Accordion>

  <Accordion title="Can r33 itself be claimed as a fee token?">
    Yes. Token selection is not allowlisted, and the contract does not exclude r33. The claim payment goes directly from the caller to the dead address, while any r33 already held by Sarcophagus can be selected like another ERC-20 balance.
  </Accordion>

  <Accordion title="Can native ETH be claimed?">
    No. `bury` and `rescue` operate on ERC-20 token contracts. Native ETH is not part of the claim interface.
  </Accordion>
</AccordionGroup>

## Security and trust boundaries

| Control             | What it provides                                         | What it does not provide                                           |
| ------------------- | -------------------------------------------------------- | ------------------------------------------------------------------ |
| Expected nonce      | Ordering and stale-call rejection                        | Exclusive execution rights or front-running protection             |
| Minimum outputs     | Lower bounds on selected pre-transfer balances           | USD pricing or guaranteed received amounts for non-standard tokens |
| `nonReentrant`      | Blocks re-entry into guarded execution                   | Compatibility with every token implementation                      |
| `SafeERC20`         | Handles standard false/no-return ERC-20 transfers        | Protection from malicious token-side semantics                     |
| Maximum token count | Bounds the current claim batch                           | A guarantee that every maximum-sized batch fits a chosen gas limit |
| Owner controls      | Operational threshold, batch-size, and rescue management | Immutable economics or guaranteed availability of accrued balances |

Searchers should assume that the owner can change the threshold or maximum token count and can rescue tokens before a claim is included. Token balances can also change independently as fees arrive or other transfers occur. Use live reads, explicit minimums, and exact-call simulation.

## Verified build

| Field                | Value                                                                                                                                                                               |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Contract             | `Sarcophagus`                                                                                                                                                                       |
| Source pragma        | `^0.8.27`                                                                                                                                                                           |
| Compiler             | Solidity `0.8.30+commit.73712a01`                                                                                                                                                   |
| Optimizer            | Enabled, `25,000` runs                                                                                                                                                              |
| IR pipeline          | `viaIR: true`                                                                                                                                                                       |
| Runtime code hash    | `0x7b368a0adab70e9752fd16d9ba71a2baddac5e8787d17a7509cb0d9816a4b967`                                                                                                                |
| Creation transaction | [`0xcd405c9afc90c62b785d819de58a15f0705b4527769ee856ff9ff056f529420b`](https://robinhoodchain.blockscout.com/tx/0xcd405c9afc90c62b785d819de58a15f0705b4527769ee856ff9ff056f529420b) |
| Verification         | Exact creation and runtime bytecode match                                                                                                                                           |

The constructor was deployed with the Ramses owner address and r33 token address listed above. The deployment is not a proxy; mutable behavior is limited to the exposed owner-controlled parameters and rescue function.

## Resources

* [Verified contract on Robinhood Blockscout](https://robinhoodchain.blockscout.com/address/0x712567e71a93Fb111510A790cAf3469677aAba3e)
* [Exact-match source on Sourcify](https://repo.sourcify.dev/4663/0x712567e71a93Fb111510A790cAf3469677aAba3e)
* [r33 / hyperRAM reference](/contracts/reference/tokens/R33)
* [Robinhood DLMM deployment reference](/contracts/reference/dlmm/deployments)
* [Fee mechanics](/concepts/protocol/fees)
