You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- A funded deployer account private key (a keystore for mainnet).
13
+
- A funded deployer account private key. The mainnet targets sign with `--interactive`, so they
14
+
prompt for the key rather than reading a variable or a keystore path.
14
15
- An Etherscan API key to verify the deployed contract (the same key works for Base via the
15
16
Etherscan v2 API).
16
17
18
+
### Who signs what on mainnet
19
+
20
+
On mainnet every privileged action goes through a Safe, and **each chain has its own pair of safes**.
21
+
The Ethereum foundation safe may not be the Base foundation safe; the same holds for the
22
+
distributors. Don't assume they match — fill each chain's config from that chain's safes rather than
23
+
copying addresses across.
24
+
25
+
|| Ethereum mainnet | Base mainnet |
26
+
| --- | --- | --- |
27
+
|**Foundation** safe — claim contract owner + proxy admin owner |`foundation` in `config.mainnet.json`|`foundation` in `config.base-mainnet.json`|
28
+
|**Distributor** safe — holds the tokens, approves the claim contract |`tokenDistributor` in `config.mainnet.json`|`tokenDistributor` in `config.base-mainnet.json`|
29
+
30
+
Deployment is the one exception: `forge script` signs with an ordinary **hot EOA**, which needs no
31
+
privileges at all — ownership is assigned from the config's `foundation` at initialization, not from
32
+
the deployer. Don't try to run a deploy from a Safe.
33
+
17
34
## Local (anvil)
18
35
19
36
A single anvil chain that deploys the token + claim contract and turns claiming on.
@@ -88,27 +105,90 @@ which it is right after deployment. Each step is also available as its own targe
88
105
89
106
## Mainnet
90
107
91
-
Covers Ethereum mainnet today. **Base mainnet: to be added later** (no claim target yet).
108
+
Both chains: **Ethereum mainnet** and **Base mainnet**. Each needs its own claim contract, its own
109
+
merkle root, and its own pair of safes (see [Who signs what on mainnet](#who-signs-what-on-mainnet)).
110
+
The ALIGN token already exists on both — you only deploy and enable `ClaimableAirdrop`.
111
+
112
+
Run Ethereum first, then Base; the two are independent apart from sharing the same
113
+
`START_TIMESTAMP` and claim deadline.
92
114
93
-
### 1. Deploy (Ethereum mainnet)
115
+
### Ethereum mainnet
94
116
95
-
Fill `script-config/config.mainnet.json` with `foundation`, `tokenDistributor`, and `tokenProxy`
96
-
(the mainnet ALIGN token), then:
117
+
#### 1. Deploy
118
+
119
+
Fill `script-config/config.mainnet.json` with the Ethereum `foundation` and `tokenDistributor` safes.
120
+
`tokenProxy` is already the mainnet ALIGN token.
97
121
98
122
```
99
-
make deploy-claimable-mainnet KEYSTORE_PATH=<keystore-path> ETHERSCAN_API_KEY=<key>
123
+
make deploy-claimable-mainnet ETHERSCAN_API_KEY=<key>
100
124
```
101
125
102
-
Note the claimable proxy address printed in the output.
126
+
Prompts for the deployer key. Note the claimable **proxy** address printed in the output (not the
127
+
implementation).
103
128
104
129
> [!NOTE]
105
-
> The mainnet ALIGN token already exists — use its address as `tokenProxy`. To deploy the token
106
-
> from scratch on Ethereum: `make deploy-token-mainnet KEYSTORE_PATH=<keystore-path>`.
130
+
> To deploy the token from scratch on Ethereum: `make deploy-token-mainnet ETHERSCAN_API_KEY=<key>`.
131
+
> You should not need this — the ALIGN token is already deployed.
132
+
133
+
#### 2. Enable claiming
134
+
135
+
Follow [Enable claiming from the safes](#enable-claiming-from-the-safes) with:
136
+
137
+
-`AIRDROP` = the claim proxy you just deployed, `TOKEN` = the mainnet ALIGN token
138
+
-`MERKLE_ROOT` = the **ethereum** root
139
+
- Owner steps from the **Ethereum foundation** safe, approve from the **Ethereum distributor** safe
140
+
141
+
### Base mainnet
142
+
143
+
#### 1. Token — already deployed, but its supply has to be bridged
144
+
145
+
The Base ALIGN token is an `OptimismMintableERC20` created through the OP factory, not with forge —
146
+
see [`base/`](base/README.md). It is pre-filled as `tokenProxy` in
147
+
`script-config/config.base-mainnet.json`.
148
+
149
+
Its balance on Base only exists to the extent it has been **bridged from Ethereum**. Claims call
150
+
`safeTransferFrom` on the distributor, so before enabling claiming the **Base distributor safe** must
151
+
hold at least the total claimable on Base.
152
+
153
+
#### 2. Fund the Base distributor safe
154
+
155
+
The **Ethereum distributor** safe bridges to the **Base distributor** safe. Since the two may be
156
+
different addresses, the deposit has to name the destination explicitly — otherwise the tokens land
157
+
at whatever address matches the sender on Base, which may be one nobody controls. Full walkthrough in
158
+
[`base/`](base/README.md#bridge-l1---base).
159
+
160
+
Takes ~20 minutes to land. Verify before continuing:
0 commit comments