@warptoad/skinny-fat-imt-js 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CREATE2.md +218 -0
- package/README.md +47 -3
- package/create2-artifacts/FatIMTPoseidon2Read.create2.json +268 -0
- package/create2-artifacts/FatIMTPoseidon2WriteEvent.create2.json +320 -0
- package/create2-artifacts/FatIMTPoseidon2WriteStorage.create2.json +320 -0
- package/create2-artifacts/SkinnyIMTPoseidon2Read.create2.json +258 -0
- package/create2-artifacts/SkinnyIMTPoseidon2WriteEvent.create2.json +301 -0
- package/create2-artifacts/SkinnyIMTPoseidon2WriteStorage.create2.json +301 -0
- package/create2-artifacts/create2-salts.json +26 -0
- package/dist/Trees.d.ts +5 -68
- package/dist/Trees.d.ts.map +1 -1
- package/dist/Trees.js +78 -41
- package/dist/Trees.js.map +1 -1
- package/dist/abis.js +1 -1
- package/dist/abis.js.map +1 -1
- package/dist/create2/create2.d.ts +144 -0
- package/dist/create2/create2.d.ts.map +1 -0
- package/dist/create2/create2.js +436 -0
- package/dist/create2/create2.js.map +1 -0
- package/dist/create2/index.d.ts +4 -0
- package/dist/create2/index.d.ts.map +1 -0
- package/dist/create2/index.js +4 -0
- package/dist/create2/index.js.map +1 -0
- package/dist/create2/interfaces.d.ts +79 -0
- package/dist/create2/interfaces.d.ts.map +1 -0
- package/dist/create2/interfaces.js +6 -0
- package/dist/create2/interfaces.js.map +1 -0
- package/dist/create2/types.d.ts +73 -0
- package/dist/create2/types.d.ts.map +1 -0
- package/dist/create2/types.js +4 -0
- package/dist/create2/types.js.map +1 -0
- package/dist/eventScanning.d.ts.map +1 -1
- package/dist/eventScanning.js +2 -2
- package/dist/eventScanning.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +71 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/package.json +9 -2
- package/src/Trees.ts +101 -99
- package/src/abis.ts +1 -1
- package/src/create2/create2.ts +643 -0
- package/src/create2/index.ts +3 -0
- package/src/create2/interfaces.ts +69 -0
- package/src/create2/types.ts +88 -0
- package/src/eventScanning.ts +31 -28
- package/src/index.ts +1 -0
- package/src/types.ts +71 -0
package/CREATE2.md
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# `@warptoad/skinny-fat-imt-js/create2`
|
|
2
|
+
TODO way too much text. Re write this claude slop
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
Deterministic CREATE2 deployment for **any** Hardhat 3 contract — not just the IMT libraries.
|
|
6
|
+
|
|
7
|
+
Freeze a contract once into a self-contained JSON artifact, then deploy it to the same address on
|
|
8
|
+
every chain, mine a vanity salt for it, and verify it on Etherscan and Sourcify. Nothing downstream
|
|
9
|
+
ever recompiles.
|
|
10
|
+
|
|
11
|
+
## Why freezing is necessary
|
|
12
|
+
|
|
13
|
+
A CREATE2 address is a function of the exact init code, and init code is **not** reproducible by
|
|
14
|
+
asking someone to compile the same source. It depends on the solc version, every optimizer setting,
|
|
15
|
+
the evm target, and — because solc's metadata hash covers the source paths — on the exact paths the
|
|
16
|
+
build assigned. Hardhat puts npm package versions in those paths, so bumping a dependency with
|
|
17
|
+
byte-identical Solidity still moves the address.
|
|
18
|
+
|
|
19
|
+
So `makeCreate2()` captures the bytes *and* the solc input that produced them. Everything after that
|
|
20
|
+
works off the frozen object.
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
makeCreate2() build time, needs Hardhat → Create2Artifact (plain JSON)
|
|
24
|
+
predictCreate2Address() pure
|
|
25
|
+
deployCreate2() runtime, viem only
|
|
26
|
+
verifyOnEtherscan() runtime, fetch only
|
|
27
|
+
verifyOnSourcify() runtime, fetch only
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Only `makeCreate2` touches Hardhat, through a dynamic import — consumers who just deploy a published
|
|
31
|
+
artifact never need Hardhat installed.
|
|
32
|
+
|
|
33
|
+
## 1. Freeze
|
|
34
|
+
|
|
35
|
+
Compile with the build profile you intend to publish, then:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { makeCreate2 } from "@warptoad/skinny-fat-imt-js/create2";
|
|
39
|
+
import { writeFile } from "node:fs/promises";
|
|
40
|
+
|
|
41
|
+
const artifact = await makeCreate2("MyContract");
|
|
42
|
+
await writeFile("MyContract.create2.json", JSON.stringify(artifact, null, 2));
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Run it inside your Hardhat project (`npx hardhat run scripts/freeze.ts`). Hardhat keeps a single
|
|
46
|
+
`artifacts/` tree rather than one per profile, so **whichever profile you compiled last is the one
|
|
47
|
+
that gets frozen**. Pin every setting in that profile — anything left to a solc default will move the
|
|
48
|
+
address on the next toolchain bump.
|
|
49
|
+
|
|
50
|
+
Constructor arguments and libraries are part of the init code, so they are frozen too:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
await makeCreate2("MyToken", { constructorArgs: ["Token", "TKN", 18n] });
|
|
54
|
+
|
|
55
|
+
await makeCreate2("SkinnyFat", {
|
|
56
|
+
libraries: { FatIMTPoseidon2WriteStorage: "0x…", /* … */ },
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Unlinked bytecode still contains `__$…$__` placeholders and is not deployable, so a contract with
|
|
61
|
+
libraries throws until you supply them. Deploy and mine the libraries first — their addresses become
|
|
62
|
+
part of this contract's init code, and therefore of its address.
|
|
63
|
+
|
|
64
|
+
Without a Hardhat project, pass the JSON yourself:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
await makeCreate2({ artifact, buildInfo, buildInfoOutput });
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## 2. Mine a vanity salt (optional)
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import { create2MiningTarget } from "@warptoad/skinny-fat-imt-js/create2";
|
|
74
|
+
|
|
75
|
+
console.log(create2MiningTarget(artifact));
|
|
76
|
+
// { factory: "0x4e59…", initCodeHash: "0x…" }
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Feed those to `create2crunch` / `createXcrunch`. Any salt works if you don't care about the address —
|
|
80
|
+
`keccak256(toBytes("v1"))` is fine.
|
|
81
|
+
|
|
82
|
+
The default factory doesn't bind the salt to a sender, so anyone can front-run the deployment. That's
|
|
83
|
+
harmless: identical init code at the same address is the outcome you wanted anyway.
|
|
84
|
+
|
|
85
|
+
> Leading zeros in a **library** address buy essentially nothing in gas — a linked library address is
|
|
86
|
+
> embedded in code as `PUSH20`, not passed in calldata, and code deposit has no zero-byte discount.
|
|
87
|
+
> Vanity here is branding.
|
|
88
|
+
|
|
89
|
+
## 3. Deploy
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { deployCreate2 } from "@warptoad/skinny-fat-imt-js/create2";
|
|
93
|
+
|
|
94
|
+
const { address, alreadyDeployed } = await deployCreate2({
|
|
95
|
+
artifact, salt, walletClient, publicClient, // factory defaults to 0x4e59…
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Idempotent — if the address already holds code it returns without sending anything, which is the
|
|
100
|
+
normal case on a chain where someone deployed before you.
|
|
101
|
+
|
|
102
|
+
**On gas:** a failed CREATE2 *does not revert the caller*. The factory's inner create returns the zero
|
|
103
|
+
address, the factory returns that, and your transaction succeeds — burning gas and deploying nothing.
|
|
104
|
+
EIP-150 forwards only 63/64 of remaining gas to the inner call, so a limit that looks sufficient can
|
|
105
|
+
leave the create just short. This bit us on a real 20KB library, where Hardhat's automatic gas came in
|
|
106
|
+
below the estimate and produced a "successful" transaction with no contract. `deployCreate2` therefore
|
|
107
|
+
estimates with headroom and re-reads the code afterwards, turning the silent failure into a thrown
|
|
108
|
+
error. Pass `gas` to override.
|
|
109
|
+
|
|
110
|
+
## 4. Verify
|
|
111
|
+
|
|
112
|
+
Both clients handle submission and polling themselves, from the frozen `solcInput` — so they work on
|
|
113
|
+
a machine with no sources and no compiler.
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { verifyOnEtherscan, verifyOnSourcify } from "@warptoad/skinny-fat-imt-js/create2";
|
|
117
|
+
|
|
118
|
+
await verifyOnEtherscan({ artifact, address, chainId, apiKey });
|
|
119
|
+
await verifyOnSourcify({ artifact, address, chainId });
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Both return `{ outcome: "verified" | "already-verified" | "failed", message }`. Sourcify also returns
|
|
123
|
+
`match`, which is `"exact_match"` when the metadata hash matched too — that only happens if your
|
|
124
|
+
profile kept it (`bytecodeHash` other than `"none"`). Etherscan uses the v2 multichain API, so one key
|
|
125
|
+
covers every supported chain.
|
|
126
|
+
|
|
127
|
+
If you're verifying a contract in the same repo that compiled it, `npx hardhat verify` works too and
|
|
128
|
+
Nomic maintains the explorer clients. These functions exist for everyone else: `hardhat-verify`
|
|
129
|
+
resolves the solc input from local build-info, so it can't help someone deploying your published
|
|
130
|
+
artifact from a repo that doesn't contain your sources.
|
|
131
|
+
|
|
132
|
+
## 5. Check a deployment independently
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import { matchesOnchainBytecode } from "@warptoad/skinny-fat-imt-js/create2";
|
|
136
|
+
|
|
137
|
+
const code = await publicClient.getCode({ address });
|
|
138
|
+
matchesOnchainBytecode(artifact, code, address);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Don't compare `deployedBytecode` directly — it never equals what's on chain, for two reasons that
|
|
142
|
+
aren't defects. solc protects public library functions from direct `CALL`s by opening the runtime code
|
|
143
|
+
with `PUSH20 <own address>; ADDRESS; EQ` and patching the real address in at construction; and
|
|
144
|
+
immutables are written the same way. Both are zeros in the compiler's output. `matchesOnchainBytecode`
|
|
145
|
+
splices the address in and masks the immutables before comparing.
|
|
146
|
+
|
|
147
|
+
## This package's own frozen artifacts
|
|
148
|
+
|
|
149
|
+
The IMT libraries are published pre-frozen, one JSON per contract, under
|
|
150
|
+
`@warptoad/skinny-fat-imt-js/create2/evm-artifacts/<Contract>`:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import type { Create2Artifact } from "@warptoad/skinny-fat-imt-js/create2";
|
|
154
|
+
import artifact from "@warptoad/skinny-fat-imt-js/create2/evm-artifacts/SkinnyIMTPoseidon2Read"
|
|
155
|
+
with { type: "json" };
|
|
156
|
+
|
|
157
|
+
await deployCreate2({ artifact: artifact as Create2Artifact, salt, walletClient, publicClient });
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Available: `SkinnyIMTPoseidon2Read`, `SkinnyIMTPoseidon2WriteEvent`, `SkinnyIMTPoseidon2WriteStorage`,
|
|
161
|
+
`FatIMTPoseidon2Read`, `FatIMTPoseidon2WriteEvent`, `FatIMTPoseidon2WriteStorage` — the same files
|
|
162
|
+
`npx hardhat gen-artifact-create2` writes to `create2-artifacts/`. A JSON import widens `0x…` strings
|
|
163
|
+
to `string`, hence the `as Create2Artifact`. Deploying one on a new chain reproduces the addresses
|
|
164
|
+
these were mined for, as long as the salt matches — the salts are published alongside them, in
|
|
165
|
+
`create2-artifacts/create2-salts.json`.
|
|
166
|
+
|
|
167
|
+
## The tasks in this repo
|
|
168
|
+
|
|
169
|
+
Four tasks, in the order you'd run them. Each defaults to the `CONTRACTS` list in
|
|
170
|
+
`tasks/create2Config.ts`, and each takes names to narrow it down.
|
|
171
|
+
|
|
172
|
+
```sh
|
|
173
|
+
npx hardhat mine-create2 --zeros 6 # salts -> create2-artifacts/create2-salts.json
|
|
174
|
+
npx hardhat gen-artifact-create2 # artifacts -> create2-artifacts/
|
|
175
|
+
npx hardhat deploy-create2 --network sepolia
|
|
176
|
+
npx hardhat verify-create2 --network sepolia
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Only the last two touch a network. `mine-create2` searches on every core and skips any contract
|
|
180
|
+
whose stored salt still lands on its stored address with enough zeros — ask for more zeros to redo
|
|
181
|
+
one. `deploy-create2` reads the frozen JSON off disk rather than recompiling, so what lands on chain
|
|
182
|
+
is what was frozen, published and verified. Salts come from `create2-salts.json`; `--salt` overrides
|
|
183
|
+
for every contract in the run.
|
|
184
|
+
|
|
185
|
+
## What invalidates an address
|
|
186
|
+
|
|
187
|
+
All of these change the init code, none of them break a build, and each needs the salt re-mined:
|
|
188
|
+
|
|
189
|
+
- a dependency bump — **even to a version with byte-identical Solidity**, since the version is in the
|
|
190
|
+
source path the metadata hash covers
|
|
191
|
+
- a comment or whitespace edit anywhere in the compilation unit
|
|
192
|
+
- any change to the build profile, or a solc upgrade
|
|
193
|
+
- different constructor arguments, or different library addresses
|
|
194
|
+
|
|
195
|
+
Worth a CI check that recompiles and asserts the frozen `initCodeHash` still matches, so a change
|
|
196
|
+
that moves an address can't land unnoticed.
|
|
197
|
+
|
|
198
|
+
## Chain caveats
|
|
199
|
+
|
|
200
|
+
- The default factory must exist on the target chain. `deployCreate2` throws with a clear message if
|
|
201
|
+
it doesn't. A different factory yields a different address.
|
|
202
|
+
- zkSync-family chains derive CREATE2 differently and cannot match these addresses at all.
|
|
203
|
+
- If your profile targets `cancun`, the bytecode may use `PUSH0`, which reverts on pre-Shanghai
|
|
204
|
+
chains. Pin `evmVersion: "paris"` for maximum reach — and decide before you mine, since changing it
|
|
205
|
+
moves every address.
|
|
206
|
+
|
|
207
|
+
## API
|
|
208
|
+
|
|
209
|
+
| Export | |
|
|
210
|
+
| --- | --- |
|
|
211
|
+
| `makeCreate2(target, options?)` | Freeze a contract into a `Create2Artifact` |
|
|
212
|
+
| `predictCreate2Address({ initCodeHash, salt, factory? })` | Pure address derivation |
|
|
213
|
+
| `create2MiningTarget(artifact, factory?)` | Inputs for a vanity miner |
|
|
214
|
+
| `deployCreate2({ artifact, salt, walletClient, publicClient, factory?, gas? })` | Idempotent deploy |
|
|
215
|
+
| `matchesOnchainBytecode(artifact, code, address)` | Compare against chain state |
|
|
216
|
+
| `verifyOnEtherscan({ artifact, address, chainId, apiKey, … })` | Submit + poll |
|
|
217
|
+
| `verifyOnSourcify({ artifact, address, chainId, … })` | Submit + poll |
|
|
218
|
+
| `DEFAULT_CREATE2_FACTORY` | `0x4e59b44847b379578588920cA78FbF26c0B4956C` |
|
package/README.md
CHANGED
|
@@ -4,6 +4,9 @@ JS library counterpart of the [skinny-fat-imt](https://github.com/warptoad/skinn
|
|
|
4
4
|
|
|
5
5
|
Reads a contract's [LeanIMT](https://github.com/privacy-scaling-explorations/zk-kit) state over viem — from storage or from events, whichever the contract exposes — and keeps a local mirror in sync.
|
|
6
6
|
|
|
7
|
+
## TODO
|
|
8
|
+
Decide where to keep the create2 artifacts and all that byte code. Using this package in frontend also downloads all that? Probably less of an issues when using bundlers?
|
|
9
|
+
|
|
7
10
|
## Install
|
|
8
11
|
|
|
9
12
|
```sh
|
|
@@ -46,6 +49,26 @@ import { queryEventInChunks, queryMultiEventsInChunks, minBigInt } from "@warpto
|
|
|
46
49
|
| --- | --- |
|
|
47
50
|
| `@warptoad/skinny-fat-imt-js` | `Trees`, `identifyTree`, `getEventFilter`, `copyTree`, `ERC165_IDS`, the ABIs, `getInterfaceId`, `DEPLOY_BLOCK`, … |
|
|
48
51
|
| `@warptoad/skinny-fat-imt-js/event-scanning` | `queryEventInChunks`, `queryMultiEventsInChunks`, `minBigInt`, `EventLog`, `PostQueryEventFilter` |
|
|
52
|
+
| `@warptoad/skinny-fat-imt-js/create2` | `makeCreate2`, `deployCreate2`, `predictCreate2Address`, `create2MiningTarget`, `verifyOnEtherscan`, `verifyOnSourcify`, `matchesOnchainBytecode` |
|
|
53
|
+
| `@warptoad/skinny-fat-imt-js/create2/evm-artifacts/<Contract>` | The frozen `Create2Artifact` JSON for each shipped IMT library |
|
|
54
|
+
|
|
55
|
+
## Deterministic CREATE2 for any contract
|
|
56
|
+
|
|
57
|
+
`/create2` is a general toolkit, independent of the IMT libraries — point it at any Hardhat 3 contract:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
const artifact = await makeCreate2("MyContract", { constructorArgs: [...] });
|
|
61
|
+
const { address } = await deployCreate2({ artifact, salt, walletClient, publicClient });
|
|
62
|
+
await verifyOnEtherscan({ artifact, address, chainId, apiKey });
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`makeCreate2` freezes the init code together with the solc input that produced it, so nothing downstream recompiles and the address holds on every chain. The IMT libraries ship pre-frozen, so bringing them to a new chain needs no compiler:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import artifact from "@warptoad/skinny-fat-imt-js/create2/evm-artifacts/SkinnyIMTPoseidon2Read" with { type: "json" };
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
See **[CREATE2.md](CREATE2.md)**.
|
|
49
72
|
|
|
50
73
|
## Development
|
|
51
74
|
|
|
@@ -53,13 +76,13 @@ import { queryEventInChunks, queryMultiEventsInChunks, minBigInt } from "@warpto
|
|
|
53
76
|
pnpm install
|
|
54
77
|
pnpm compile # hardhat compile, then regenerate src/abis.ts
|
|
55
78
|
pnpm test # hardhat test
|
|
56
|
-
pnpm typecheck # tsc over src + test + hardhat.config.ts
|
|
79
|
+
pnpm typecheck # tsc over src + test + scripts + hardhat.config.ts
|
|
57
80
|
pnpm build # emit dist/ from src/ via tsconfig.build.json
|
|
58
81
|
```
|
|
59
82
|
|
|
60
83
|
### About `src/abis.ts`
|
|
61
84
|
|
|
62
|
-
`src/abis.ts` is **generated and committed**. `scripts/genAbis.
|
|
85
|
+
`src/abis.ts` is **generated and committed**. `scripts/genAbis.ts` copies nine ABIs out of hardhat's `artifacts/` into `as const` tuples.
|
|
63
86
|
|
|
64
87
|
The library deliberately does not import `artifacts/` directly, even though that's the obvious thing to do. `artifacts/` is gitignored, ~13MB, and hardhat's generated `artifacts.d.ts` files end with:
|
|
65
88
|
|
|
@@ -71,6 +94,14 @@ Shipping that would make the published typings require `hardhat` to be resolvabl
|
|
|
71
94
|
|
|
72
95
|
**Whenever the contracts change, run `pnpm compile` and commit the resulting `src/abis.ts` diff.** Nothing regenerates it automatically at publish time — that's on purpose, so `npm publish` can never silently rewrite source.
|
|
73
96
|
|
|
97
|
+
## deployment
|
|
98
|
+
```
|
|
99
|
+
pnpm hardhat gen-artifact-create2 --network sepolia;
|
|
100
|
+
pnpm hardhat mine-create2 --network sepolia --zeros 6;
|
|
101
|
+
pnpm hardhat deploy-create2 --network sepolia;
|
|
102
|
+
pnpm hardhat verify-create2 --network sepolia;
|
|
103
|
+
```
|
|
104
|
+
|
|
74
105
|
## Publishing to npm
|
|
75
106
|
|
|
76
107
|
### One-time setup
|
|
@@ -110,7 +141,7 @@ npm whoami # confirm the right account
|
|
|
110
141
|
npm pack --dry-run
|
|
111
142
|
```
|
|
112
143
|
|
|
113
|
-
Expect `dist/**`, `src/**`, `README.md`, `LICENSE`, `package.json` — about 50KB. If you see `artifacts/` or a multi-MB tarball, something is wrong with `files` in package.json.
|
|
144
|
+
Expect `dist/**`, `src/**`, `README.md`, `CREATE2.md`, `LICENSE`, `package.json` — about 50KB. If you see `artifacts/` or a multi-MB tarball, something is wrong with `files` in package.json.
|
|
114
145
|
|
|
115
146
|
4. Publish. `prepublishOnly` runs `pnpm build` (a clean `rm -rf dist` then `tsc -p tsconfig.build.json`), so `dist/` is always rebuilt from current source:
|
|
116
147
|
|
|
@@ -143,9 +174,22 @@ pnpm add @warptoad/skinny-fat-imt-js viem
|
|
|
143
174
|
node -e "import('@warptoad/skinny-fat-imt-js').then(m => console.log(Object.keys(m)))"
|
|
144
175
|
```
|
|
145
176
|
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
146
180
|
### Notes
|
|
147
181
|
|
|
148
182
|
- **You cannot republish a version.** Once `0.0.1` is out, `0.0.1` is taken forever, even if you unpublish. Bump and move on.
|
|
149
183
|
- `npm unpublish` is only allowed within 72 hours, and only if nothing depends on it. Use `npm deprecate` instead for anything older.
|
|
150
184
|
- If publish fails with `402 Payment Required`, `publishConfig.access` got lost — scoped packages need `"access": "public"`.
|
|
151
185
|
- If it fails with `404`, you're either not logged in or not a member of the `@warptoad` scope.
|
|
186
|
+
|
|
187
|
+
## Deployed addresses sepolia
|
|
188
|
+
```
|
|
189
|
+
SkinnyIMTPoseidon2WriteStorage 0x00000066C760D24272a9E8A424EF7233A0F0da83
|
|
190
|
+
SkinnyIMTPoseidon2WriteEvent 0x000000D74387530f88b9Cf1A23CDf16fdDC01bf6
|
|
191
|
+
SkinnyIMTPoseidon2Read 0x000000A3a94867DD396753dEFABF989246211329
|
|
192
|
+
FatIMTPoseidon2WriteStorage 0x000000F35EFB6F537d3663CF263c04f467f48c73
|
|
193
|
+
FatIMTPoseidon2WriteEvent 0x00000012de70B336818C26517A4B2d7c0B949C7b
|
|
194
|
+
FatIMTPoseidon2Read 0x000000FF3329863F1Eb55773aDEF01863791370
|
|
195
|
+
```
|