> For the complete documentation index, see [llms.txt](https://igra-labs.gitbook.io/igralabs-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://igra-labs.gitbook.io/igralabs-docs/for-developers/architecture/specifications/igra-bootstrap.md).

# Igra Bootstrap

**Last updated**: 2026-02-05

## Table of Contents

1. [Overview](#overview)
2. [Genesis State](#genesis-state)
3. [Other Bootstrap Helper Contracts](#other-bootstrap-helper-contracts)
4. [Igra Core Contracts](#igra-core-contracts)
5. [Deployment Order](#deployment-order)
6. [The Configuration Transaction](#the-configuration-transaction)
7. [Complete Bootstrap Flow](#complete-bootstrap-flow)
8. [Pre-Governance Deployer Actions](#pre-governance-deployer-actions)
9. [Post-Bootstrap Governance Proposals](#post-bootstrap-governance-proposals)
10. [Bootstrap Configuration File](#bootstrap-configuration-file)
11. [Appendix: CREATE2 Address Calculation](#appendix-create2-address-calculation)
12. [Appendix: Configurator Account Address Computation](#appendix-configurator-account-address-computation)

***

## Overview

The ultimate purpose of the Igra L2 bootstrap process is deployment and configuration of the Core Contracts in a trustless, deterministic, and cryptographically committed way.

This document describes the complete bootstrap process, including:

* Genesis state configuration
* Deterministic deployment via CREATE2 (DDP)
* One-time configuration transaction orchestrated by `ConfTxExecutor` and executed by `AuthorizedMulticall`
* Ownership and permission setup

The approach is a **single Configuration Transaction** sent from a one-time Configurator EOA. The transaction deploys `ConfTxExecutor` (init-only) via DDP. `ConfTxExecutor` deploys `AuthorizedMulticall`, forwards configuration calls to it, triggers its self-destruct, and returns empty runtime code.

***

## Genesis State

**Bytecode note**: bytecode snippets below are duplicated for convenience. The authoritative sources are the files in `src/bootstrap/` (`*.hex` or `*.hex.template`). If any mismatch occurs, the `src/bootstrap` files are correct.

### Accounts pre-configured via the Genesis

| Address                                      | Contract / Data                | Notes                                                       |
| -------------------------------------------- | ------------------------------ | ----------------------------------------------------------- |
| `0x000000000000000097b100000000000000000000` | Non-executable text message    | "Igra" message                                              |
| `0x0000F90827F1C53a10cb7A02335B175320002935` | EIP-2935 BLOCKHASH history     | Stores historical block hashes                              |
| `0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02` | Modified EIP-4788 Beacon Roots | Stores historical L1 chain data                             |
| `0xFe38D0727B928E19bE51673Ac0691Ca22C05B1B3` | Extended EIP-4788 Reader       | Getter for historical L1 chain data                         |
| `0x4e59b44847b379578588920ca78fbf26c0b4956c` | Deterministic Deployment Proxy | CREATE2 deployer for all contracts                          |
| `0x0000000000000000000000000000000000000FEE` | Minimal ERC-1967 proxy         | Upgradable proxy for `Fee` contract                         |
| `0x9063d52b68d8883c882a5d4c34b0e4d58ba4b356` | ConfiguratorGetter             | Runtime-only getter for the Configurator address            |
| `0x9a232acf6dd107483d3466494b8e0cd39da1828d` | TsReferenceGetter              | Runtime-only getter for `REF_DAA_SCORE` and `REF_TIMESTAMP` |

### Igra message

**Address**: `0x000000000000000097b100000000000000000000`

**Bytecode**:

```
0x005d05b25e85b55d9205ea5b45d15b05e05b55d9205d15bc5b55d95ea5b85d0205d75b75d35b05ea5bc5b85d0205d55b05ea5b75e25b05d15bc5b55d3205ea5bc5b05d95b85e75b85d0205dc5b05d05b45d25bc5b05e85b85da5b0205d55b05dc5b85d0205ea5b05e95c15b75d55bc5b45d9205d75d55b95d15b75ea205d35bc5b45d95df205d35b45e75b05d85d55b95dc205d15bc5b05d15b55d95ea5b85da5b0205d05b25e85b55d9205d95b45e45bc5b55dc205d35bc5b05e05b85e45b55dc205de5b45e05bc5b55d95d45bc3a
```

**Behavior**:

* The "bytecode" is the UTF8-encoded text of the verse Deuteronomy 22:8 (Aramaic translation), prepended with 0x00 byte (EVM's "halt execution" opcode) to prevent accidental call execution.

### ConfiguratorGetter

**Address**: `0x9063d52b68d8883c882a5d4c34b0e4d58ba4b356`

**Bytecode template** (runtime only, placeholder must be replaced):

```
0x73{configurator_address}5f5260205ff3
```

**Behavior**:

* Returns the Configurator address as a 32-byte ABI word.
* `{configurator_address}` is the precomputed one-time Configurator Account address (40 hex chars, no `0x`).

### TsReferenceGetter

**Address**: `0x9a232acf6dd107483d3466494b8e0cd39da1828d`

**Bytecode template** (runtime only, placeholders must be replaced):

```
0x67{ref_daa_score}5f5267{ref_timestamp}60205260405ff3
```

**Behavior**:

* Returns `(REF_DAA_SCORE, REF_TIMESTAMP)` as `(uint64,uint64)` ABI-encoded values.
* `{ref_daa_score}` and `{ref_timestamp}` are precomputed values (16 hex chars each, no `0x`).

### Fee Proxy

**Address**: `0x0000000000000000000000000000000000000FEE`

**Bytecode** (runtime only):

```
0x365f80375f807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc548136915af43d5f803e156038573d5ff35b3d5ffd
```

**Storage**:

```
// ERC-1967 Implementation slot set to the precomputed ProxyUpgrader address
storage[0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc] = address(ProxyUpgrader)
```

**Behavior**:

* Minimal ERC-1967 compatible proxy (EIP-1167 style).
* Reads implementation address from the ERC-1967 slot and DELEGATECALLs with identical calldata.
* Bubbles return or revert data as-is.

### EIP-2935 BLOCKHASH history contract

**Address**: `0x0000F90827F1C53a10cb7A02335B175320002935`

**Bytecode**:

```
0x3373fffffffffffffffffffffffffffffffffffffffe14604657602036036042575f35600143038111604257611fff81430311604257611fff9006545f5260205ff35b5f5ffd5b5f35611fff60014303065500
```

**Behaviour**:

* Stores the history of BLOCKHASHES for recent blocks.
* Refer to [EIP-2935](https://eips.ethereum.org/EIPS/eip-2935) for details.

### Modified EIP-4788 Beacon Roots history contract

**Address**: `0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02`

**Bytecode**:

```
0x3373fffffffffffffffffffffffffffffffffffffffe14607d57602036146024575f5ffd5b5f358015607957611fff810690815414603b575f5ffd5b611fff0180545f523373fe38d0727b928e19be51673ac0691ca22c05b1b3146063575060205ff35b611fff018054602052611fff015460405260605ff35b5f5ffd5b611fff4206428155611fff015f358155611fff01448155611fff0143905500
```

**Behavior**:

* It is the modified [EIP-4788 Beacon Root History contract](https://eips.ethereum.org/EIPS/eip-4788) used by Igra.
* Stores recent `beaconRoot` and `prevRanDao` values to enable cryptographic linking L2 and L1 blocks.
* Refer to the [documentation here](https://github.com/IgraLabs/igra-eip4788-modifications).

### Extended EIP-4788 Reader

**Address**: `0xFe38D0727B928E19bE51673Ac0691Ca22C05B1B3`

**Bytecode**:

```
0x365f5f375f5f365f73000f3df6d732807ef1319fb7b8bb8522d0beac025afa3d5f5f3e15602a573d5ff35b3d5ffd
```

**Behavior**:

* Forwards calls to the Modified EIP-4788 Beacon Roots history contract.
* Refer to the [documentation here](https://github.com/IgraLabs/igra-eip4788-modifications).

### Deterministic Deployment Proxy (DDP)

**Address**: `0x4e59b44847b379578588920ca78fbf26c0b4956c`

**Bytecode**:

```
0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3
```

**Behavior**:

* When CALLed, deploys a bytecode and the "salt" provided as `calldata`, using CREATE2, at an address that depends on the bytecode and the "salt" only.
* Used to deploy contracts to known in advance addresses.
* Refer to [https://github.com/Zoltu/deterministic-deployment-proxy](https://github.com/Zoltu/deterministic-deployment-proxy/tree/master) for further details.

***

## Other Bootstrap Helper Contracts

In addition to contracts injected directly into the genesis (see "Genesis State"), the following contracts are deployed during the bootstrap process and serve as helper contracts:

* `ProxyUpgrader` (deployable, reads configurator from `ConfiguratorGetter`, checks `tx.origin`, writes the ERC-1967 slot, selfdestructs)
* `AuthorizedMulticall` (deployable, checks `tx.origin`, executes `bytes[]` calls atomically, selfdestructs)
  * **Precomputed address**: `0x72E934AE4917E1778043Ad28458190Ea019Df79A`
  * Deployed via DDP with salt `0x97b1` (32 bytes zero-padded)
  * This address is hardcoded in `ConfTxExecutor` for efficiency
* `ConfTxExecutor` (init-only, deploys and drives `AuthorizedMulticall`, returns empty runtime)

Sources and bytecode: `src/bootstrap/proxyUpgrader/`, `src/bootstrap/authorizedMulticall/`, `src/bootstrap/confTxExecutor/`.

***

## Configurator (and its address)

This is a one-time-use EOA whose address is a cryptographic commitment to the exact Configuration Transaction. If any single byte in the Configuration Transaction changes (including any change to core-contract bytecode or parameters), the derived Configurator address changes as well.

Key points:

* The Configurator address is computed **after** all configuration parameters are finalized.
* It is embedded in genesis via the runtime bytecode of `ConfiguratorGetter`.
* The Configuration Transaction is sent **from this address**.
* Before sending the Configuration Transaction the address shall be funded to pay gas for that transaction.

Private key properties:

* The private key is provably unknown. The public key (and address) is derived by `ecrecover` from a fixed signature (derived from `keccak256(0x97b1)`) over the precomputed Configuration Transaction.
* Because no private key is known, **only this single pre-computed transaction** can be sent from this address.

***

## Igra Core Contracts

These contracts are the core protocol components. Their deployment and configuration is the ultimate purpose of the bootstrap process.

* `Diamond` (the diamond proxy) - `src/diamond/Diamond.sol`
* System facets: `DiamondCutFacet`, `DiamondLoupeFacet`, `OwnershipFacet` - `src/diamond/facets/`
* Attestations facets - `src/attestation/facets/`:
  * `ConfigInit`
  * `Staking`
  * `Attester`
  * `Challenger`
  * `Config`
* `L2Oracle` (attestation system library; reads reference points from `TsReferenceGetter`) - `src/common/L2Oracle.sol`
* IGRA Token and vesting contracts:
  * `IgraToken` - `src/IgraToken.sol`
  * `VestingPools` - `src/VestingPools.sol`
* DAO Governance contracts:
  * `IgraVotingPower` - `src/IgraVotingPower.sol`
  * `Governance` - `src/Governance.sol`

These contracts are deployed via the DDP (CREATE2). Because CREATE2 binds address to bytecode, their addresses are a cryptographic commitment to their bytecode.

***

## Deployment Order

This flow is aligned with `docs/configurationTransaction.md` and `src/bootstrap` contracts.

1. **Pre-compute addresses** for:
   * `ProxyUpgrader` (CREATE2 via DDP)
   * `AuthorizedMulticall` (CREATE2 via DDP, fixed salt + fixed bytecode)
   * Configurator (one-time EOA)
   * `ConfTxExecutor` (CREATE2 via DDP)
2. **Genesis**:
   * Inject runtime code for `ConfiguratorGetter` and `TsReferenceGetter` with precomputed values.
   * Inject minimal proxy runtime at `0x...0FEE` and set its implementation slot to the precomputed `ProxyUpgrader` address.
3. **Deployer deploys core contracts via DDP**:
   * When applicable, deploy contracts with the **precomputed `AuthorizedMulticall` address as temporary owner/guardian**.
4. **Configuration Transaction** (single, atomic):
   * Configurator EOA sends a single transaction to DDP with `ConfTxExecutor` init code and arguments.
   * DDP deploys `ConfTxExecutor`, which executes:
     1. Deploy `AuthorizedMulticall` via DDP.
     2. Forward the `bytes[]` configuration payload to `AuthorizedMulticall`.
     3. Call `AuthorizedMulticall` with empty calldata to selfdestruct.
     4. Return empty runtime code.
   * `ProxyUpgrader` deployment, proxy upgrade call, and `ProxyUpgrader` selfdestruct are encoded in the forwarded `bytes[]` payload and executed by `AuthorizedMulticall`.

***

## The Configuration Transaction

The Configuration Transaction is a **single, atomic** transaction sent by the Configurator EOA. It uses the DDP to deploy `ConfTxExecutor` whose constructor executes a scripted list of calls.

Key properties:

* **Init-only execution**: `ConfTxExecutor` returns **zero-length runtime code**.
* **Contextful calls**: all protocol configuration calls are executed with `msg.sender == AuthorizedMulticall`.
* **Deterministic addresses**: Configurator, ConfTxExecutor and AuthorizedMulticall addresses are known before execution.
* **Atomicity**: any failure reverts the entire transaction.

Constructor input is `bytes[] data` (no selector). Each entry is:

```
abi.encode(address to, bytes callData)
```

Because init code has **no calldata**, the args are appended to the init code and suffixed with a 2-byte big-endian length:

```
<init_code> || <args> || <uint16(args_len)>
```

Any revert bubbles revert data and fails the entire transaction.

***

## Complete Bootstrap Flow

### Step 1: Genesis Block Creation

Genesis includes:

* Runtime code for `ConfiguratorGetter` and `TsReferenceGetter` with precomputed values
* Minimal proxy at `0x...0FEE` with implementation slot set to the precomputed `ProxyUpgrader` address
* Deterministic Deployment Proxy (DDP)

### Step 2: Core Contract Deployments

Deployer deploys core contracts via DDP (CREATE2). When applicable, contracts are deployed with the **precomputed `AuthorizedMulticall` address as temporary owner**.

### Step 3: Top Up Configurator address

```
Deployer -> Configurator address
```

The Configurator address is topped up with iKAS to pay gas for the Configuration Transaction.

### Step 4: Configuration Transaction

Configurator EOA sends the configuration transaction to DDP. `ConfTxExecutor` runs, deploys helper contracts, forwards the configuration payload to `AuthorizedMulticall`, destroys helpers, and returns empty runtime code.

### Step 5: Post-Bootstrap State

After successful configuration:

| Contract               | Owner      | Notes                            |
| ---------------------- | ---------- | -------------------------------- |
| Fee (0xFee)            | Governance | Releaser not set yet             |
| Attestation (Diamond)  | Governance | Fully configured diamond         |
| StakeRewardsController | Governance | Emission rate not set yet        |
| VestingPools           | Governance | All pools added                  |
| IgraToken              | -          | MINTER = VestingPools            |
| Governance             | -          | Autonomous (no voting power yet) |

***

## Pre-Governance Deployer Actions

After bootstrap, the deployer EOA must perform these actions **before any governance proposals**:

```solidity
// 1. Release attester stake tokens to deployer
VestingPools.releaseTo(attesterPoolId, deployerEOA, totalStakeAmount)

// 2. Approve Diamond to pull tokens
IgraToken.approve(diamond, totalStakeAmount)

// 3. Register initial attesters
diamond.register(attester1Address, stake1Amount)
diamond.register(attester2Address, stake2Amount)
// ... repeat for each attester

// 4. Update Igra Association pool wallet to multisig
VestingPools.updateWallet(igraAssociationPoolId, igraAssociationMultisig)
```

After these actions, attesters have voting power via `IgraVotingPower` (from staked IGRA token), and the Igra Association multisig can gain voting power by releasing IGRA token from their pool, enabling governance proposals.

***

## Post-Bootstrap Governance Proposals

After deployer actions complete, the following configurations are assumed to be done via governance proposals:

### 1. Enable Fee Releases

```solidity
Fee.updateReleaser(diamond)
```

Sets the Diamond (Attestation) as the authorized releaser for iKAS rewards and gas refunds.

### 2. Enable IGRA emission

```solidity
// Release IGRA from a vesting pool to StakeRewardsController
// Typically Pool 0 (Ecosystem & Rewards), but configurable via governance
VestingPools.releaseTo(poolId, stakeRewardsController, rewardsAmount)

// Enable IGRA emissions to attesters
StakeRewardsController.setEmissionRate(emissionNumerator)
```

Starts topping-up the reward pool for attesters with IGRA tokens. Value is in pips (1 pip = 0.01% APY).

***

## Bootstrap Configuration File

All configurable parameters are defined in a bootstrap config file:

* **Configurator Address** for `ConfiguratorGetter`
* **Reference points** for `TsReferenceGetter` (`l1ReferenceTimestamp`, `l1ReferenceDaaScore`), used by `L2Oracle`
* **Emission rate** for `StakeRewardsController` (`emissionNumerator` in pips)
* **Initial config params** for `ConfigInit` (`minStakeAmount`, `activationDelayBlocks`, `exitCooldownBlocks`, etc.)
* **Initial attesters** (addresses, stake amounts, vesting schedules)
* **Vesting pool definitions**

***

## Appendix: CREATE2 Address Calculation

For each contract, the address is calculated as:

```
address = keccak256(
    0xff,
    deployerProxy,  // 0x4e59b44847b379578588920ca78fbf26c0b4956c
    salt,           // 0x97b1
    keccak256(bytecode + constructorArgs)
)[12:]
```

The deployment transaction is sent to the Deterministic Deployment Proxy with:

* `data = salt + bytecode + constructorArgs`

***

## Appendix: Configurator Account Address Computation

The Configurator account address is **computed as follows**:

1. Craft the configuration transaction with all calls defined and compute its hash `txHash`.
2. Deterministically derive the signature values `(v, r, s)` from a fixed seed (e.g., `0x97b1`).
3. The sender address is derived as `ecrecover(txHash, v, r, s)`.
4. Include this address in the bytecode of `ConfiguratorGetter` (in genesis).

**Before broadcasting the Configuration Transaction** the computed address must be topped up with enough iKAS to pay for Configuration Transaction gas.

The Configuration Transaction succeeds because:

* The signature is mathematically valid.
* The derived address has balance for gas.

As no one knows the private key (only this specific transaction can ever be sent from this address), this creates a trustless, deterministic, and cryptographically committed Configuration Transaction.
