> For the complete documentation index, see [llms.txt](https://docs.usegimbal.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.usegimbal.app/architecture/build-and-deploy.md).

# Build and deploy

Compiling and testing the Gimbal contracts, what the deploy script does in what order, the variables it reads, the notes that matter on Robinhood Chain, and where the live addresses are recorded.

Gimbal's contracts form a Foundry project under `contracts/` in the repository: Solidity 0.8.26, the Cancun EVM and via-IR, fixed in `foundry.toml`. Dependencies (forge-std 1.9.7, OpenZeppelin 5.2.0) come through soldeer, not git submodules.

```bash
cd contracts
forge soldeer install
forge build
forge test -vv
```

## The addresses that count

`contracts/deployments/4663.json` is the one authoritative list of the live contracts on Robinhood Chain (4663). The platform's `deployment` parameter row carries the same addresses, and the Explorer's parameters panel prints the desk address. An address absent from that file is untrusted. Each deployment's source is verified on Blockscout. See [Reading the Explorer](/guides/explorer.md) and [Network parameters](/robinhood-chain/parameters.md).

## The test suite

`forge test` runs 109 tests across eight files (nine suites), all built on `Base.t.sol`, a fixture that deploys the stack with mocks and signs offers and requests.

| File                      | Ground covered                                                                                                                                                                                                                                                                                                                                                                  |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Origination.t.sol`       | A three-lender syndicate; the tier LTV ceiling; ineligible borrower and lender; APR above the borrower's maximum; cancelled offers; one standing offer feeding two loans; the relayer path; exposure caps; the guardian's pause; funding from parked capital; request replay; the slice cap; slice transfer gating; sequencer grace; overflow guards                            |
| `Repayment.t.sol`         | Per-slice accrual; repayment by a third party; the minimum interest period; partial and full repayment; top-ups; paying during grace, under a new-loan pause and after a failed rollover                                                                                                                                                                                        |
| `CollateralAuction.t.sol` | Health factor against price; a whole Dutch auction to the proceeds waterfall; partial buys; liquidator gating; default once grace ends; sequencer grace; an oracle pause; stale and quiet feeds by session; the closed-market haircut, floor and opt-outs; the move cap and its checkpoints; in-kind payout; the stream report requirement; pause and restart of a stalled sale |
| `Rollover.t.sol`          | Who may open and when; the linear rate climb; clearing with a fresh syndicate; failure into default; offers above the current rate; borrower cancellation; capacity returned after failure or liquidation; the acceptance cap                                                                                                                                                   |
| `Policy.t.sol`            | Bootstrap and the timelock; stale batches; the guardian's reach; parameter validation; attestation expiry and revocation; issuer removal; the gated slice transfer; treasury withdrawal; one-shot wiring                                                                                                                                                                        |
| `PriceSentinel.t.sol`     | Feed configuration and its rejections; the quote token; sequencer rounds; stream reports that are fresh, stale, undated, future-dated or divergent; prices that rescale to zero                                                                                                                                                                                                 |
| `Parking.t.sol`           | Parking and withdrawal with yield; overdraw protection; desk-only access; retiring a vault without stranding balances                                                                                                                                                                                                                                                           |
| `Invariants.t.sol`        | A handler-driven invariant over the loan ledger plus fuzzed partial repayments, syndicate splits and liquidations                                                                                                                                                                                                                                                               |

[Assurance](/architecture/assurance.md) covers what surrounds the suite: fuzzing, mutation, forks, formal verification and audits.

## Deploying

Copy `.env.example` to `.env` and fill in at least `PRIVATE_KEY` and `ROBINHOOD_RPC` (official RPC URLs: docs.robinhood.com/chain). For a live chain also set `STOCK_TOKEN`, `STOCK_FEED`, `USDG` and `VAULT`. Then:

```bash
source .env
forge script script/Deploy.s.sol --rpc-url robinhood --broadcast --verify
```

One run does everything, in this order:

1. Deploys `PolicyBoard`, `RoleRegistry`, `AttestationLedger`, `PriceSentinel`, `LenderSlice`, `Treasury`, `TermDesk`, `CollateralAuction` and `RolloverAuction`.
2. Writes policy while the board is still in bootstrap: the ledger as eligibility adapter, the attestation issuer, tiers 1 to 3 (shown as A to C), the first collateral token with its cap, USDG as loan token, the 7, 14, 30 and 90 day terms, the loan, auction, rollover and fee parameters, and the vault whitelist.
3. Configures the collateral feed on the sentinel, plus Chainlink's sequencer uptime feed when one is given.
4. Deploys `ParkingAdapter`, then calls `LenderSlice.setDesk`, `ParkingAdapter.setDesk` and `TermDesk.wire`.
5. Calls `finishBootstrap()` if asked, and starts the two-step handover to the governance multisig, which completes it with `acceptOwnership()`.

Every address lands in `contracts/deployments/<chainId>.json` under the keys `chainId`, `PolicyBoard`, `RoleRegistry`, `AttestationLedger`, `PriceSentinel`, `LenderSlice`, `Treasury`, `TermDesk`, `CollateralAuction`, `RolloverAuction`, `ParkingAdapter`, `USDG`, `StockToken`, `StockFeed` and `Vault`. The seed scripts and the platform read that file.

### Variables the script reads

| Variable                                                                             | Purpose                                                                                                    |
| ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
| `PRIVATE_KEY`                                                                        | The deployer, who owns `PolicyBoard` until `GOV` takes over                                                |
| `ROBINHOOD_RPC`, `ROBINHOOD_TESTNET_RPC`                                             | Endpoints behind the `robinhood` and `robinhood_testnet` aliases                                           |
| `STOCK_TOKEN`, `STOCK_FEED`, `USDG`, `VAULT`                                         | Tier 1 collateral, its Chainlink feed, the loan token, the ERC-4626 vault for parked capital               |
| `SEQUENCER_FEED`                                                                     | Chainlink's L2 Sequencer Uptime Feed; skipped when blank                                                   |
| `MARKET_STATUS_SOURCE`                                                               | A contract exposing `marketStatus()` for session classification; blank means the sentinel's clock schedule |
| `STREAM_ADAPTER`                                                                     | Adapter for the Data Streams verifier that auction pricing uses; blank means Data Feeds alone              |
| `STALENESS_REGULAR`, `STALENESS_EXTENDED`, `STALENESS_CLOSED`                        | Staleness bounds per session in seconds; defaults 3600, 7200 and 345600                                    |
| `MOVE_CAP_WINDOW`                                                                    | Checkpoint window for the 25 percent move cap, in seconds; default 3600                                    |
| `GOV`, `GUARDIAN`                                                                    | Governance multisig; pause key holder. Both default to the deployer                                        |
| `TIMELOCK_DELAY`                                                                     | Seconds; default 3600. Once bootstrap is over it cannot go below 3600 again                                |
| `ATTESTATION_ISSUER`                                                                 | KYC signer permitted to write attestations; defaults to the deployer                                       |
| `FINISH_BOOTSTRAP`                                                                   | `true` closes bootstrap as the last step, so every later change goes through the timelock                  |
| `DEPLOY_MOCKS`                                                                       | `true` lets a mock stand in for any blank dependency; defaults to true on every chain except 4663          |
| `ROBINHOOD_BLOCKSCOUT_API`, `ROBINHOOD_TESTNET_BLOCKSCOUT_API`, `BLOCKSCOUT_API_KEY` | Verification endpoints; the key is `unused`                                                                |

`DeployCore.s.sol` is the lighter testnet variant (`PolicyBoard`, `TermDesk`, `CollateralAuction` and their dependencies; no `RolloverAuction`, `ParkingAdapter` or `Treasury`). `Seed.s.sol` and `SeedDeep.s.sol` exercise a full deployment; the latter shortens the delay to a minute so `SeedExecute.s.sol`, run a minute later, applies a queued change and restores the hour. `SeedCore.s.sol`, `SeedMore.s.sol` and `SeedResume.s.sol` do the same for a core-only one.

## Notes for Robinhood Chain testnet (46630)

* `TermDesk` sits a few hundred bytes under the 24,576-byte EIP-170 limit. Run `forge build --sizes` after touching the desk. Past the limit, a deployment only lands with `--code-size-limit 1000000` (and `--disable-code-size-limit` against a local Anvil fork); needing either flag means the desk should be trimmed, not that the flag should stay.
* Verification goes through Blockscout, not Etherscan: add `--verify --verifier blockscout --verifier-url https://explorer.testnet.chain.robinhood.com/api/` to the deploy command, or verify afterwards with `--broadcast --resume --private-key $PRIVATE_KEY` plus the same flags.
* Use `--gas-estimate-multiplier 200 --slow`. L1 calldata is billed as extra gas units, so the limits forge derives from simulation undershoot on heavier calls; a doubled estimate, one transaction at a time, gets through.
* Set `GOV` so the run ends by offering `PolicyBoard` to the multisig, and `FINISH_BOOTSTRAP=true` so the timelock is in force from then on.

## Running locally

Against Anvil, leave every dependency address blank. The script deploys a mock USDG with six decimals, a mock `NVDAx` Stock Token, a mock Chainlink aggregator reporting 176.40 with eight decimals, plus a mock ERC-4626 vault. When the issuer is the deployer it also attests the deployer as `BORROWER`, `LENDER_PROFESSIONAL`, `LIQUIDATOR` and `RELAYER`. The lifecycle then runs end to end:

1. Give a lender mock USDG and a borrower mock Stock Tokens; approve `TermDesk` for both.
2. Sign a `LendOffer` as EIP-712 typed data: domain name `Gimbal`, version `1`, the chain id of the local node, and `TermDesk` as verifying contract.
3. The borrower then calls `originate(request, "", [offer], [signature])`.
4. Inspect `debtOf`, `healthFactor` and the `LenderSlice` balance.
5. Either `repay`, or lower the price through `MockAggregatorV3.set()` and open a sale with `CollateralAuction.startAuction`.

No mock is ever part of a production deployment. [The contract set](/architecture/contracts.md) describes what each contract does once it is up.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.usegimbal.app/architecture/build-and-deploy.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
