chore(injective): mainnet deploy config - #4
Merged
Conversation
Injective mainnet (chain 1776). Closes G-6's core third — the AMM could not be deployed from this repo at all, because `BaseScript` resolves `SCRIPT_CONFIG` to a file that did not exist. Two addresses are filled and both are DERIVED, not chosen: - `create3Factory` 0xa4753315… is CREATE(0x02E0d5Fd…, 0). The factory is deployed by plain CREATE from a dedicated nonce-0 EOA — never through the Arachnid CREATE2 deployer, which would make that stub the owner and sole whitelisted user and brick the factory permanently. CREATE(eoa, 0) depends on nothing else, so the address is knowable today. Confirmed with `cast compute-address`. - `poolOwner` / `protocolFeeControllerOwner` 0x8a3c2cDa… is the mainnet TimelockController at salt CHOICE-V2/TimelockController/1.0.0. CREATE3 derives an address from the salt and the factory alone, so this is knowable before script 01 has ever run. Derived by executing the DEPLOYED testnet factory's bytecode at the mainnet factory address (`cast call --override-code`); the same method reproduces testnet's own timelock 0xfE9811111C… exactly, which is the control that makes the number trustworthy rather than merely computed. Every deployed-address field is "0x", following ethereum-mainnet.json. That is not cosmetic: `getAddressFromConfig` decodes an unset value to address(0x20) and reverts "Address not set", so a script run before its dependency has landed stops instead of deploying something wired to address(0). Proven both ways — the two filled keys decode to the addresses above, and reading `vault` reverts. 🔴 These hold only if the factory is deployed from 0x02E0d5Fd… at nonce 0. All predicted addresses were checked EMPTY on 1776 before this was written. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
script/config/injective-mainnet.json, soSCRIPT_CONFIG=injective-mainnetresolves.Closes the infinity-core third of G-6 in
SECURITY_AUDIT_2026-09-08.md— the audit'sfinding was that the AMM could not be deployed to mainnet from the repo at all, because
BaseScriptresolvesSCRIPT_CONFIGto a file that did not exist.A3 of Batch A. No
src/change, no test change, no deployed bytecode change.The two filled addresses are DERIVED, not chosen
create3Factory0xa4753315…07Df5CREATE(0x02E0d5Fd…, 0)— confirmed withcast compute-addresspoolOwner,protocolFeeControllerOwner0x8a3c2cDa…bE10CHOICE-V2/TimelockController/1.0.0The factory is deployed by plain CREATE from a dedicated nonce-0 EOA, never through the
Arachnid CREATE2 deployer — its constructor does
Ownable(msg.sender)andisUserWhitelisted[msg.sender] = true, so going through the deployer would make that stub theowner and sole whitelisted user and brick the factory permanently.
CREATE(eoa, 0)depends onnothing else, which is what makes the address knowable before anything is deployed.
The timelock follows because CREATE3 derives an address from the salt and the factory alone.
It was derived by executing the deployed testnet factory's own bytecode at the mainnet factory
address (
cast call --override-code) — and the control that makes it trustworthy rather thanmerely computed is that the same method reproduces testnet's live timelock
0xfE9811111C…exactly.
🔴 Both hold only if the factory is deployed from
0x02E0d5Fd…at nonce 0. Every predictedaddress was checked EMPTY on 1776 before this was written.
Why every deployed-address field is
"0x"Following
ethereum-mainnet.json, and it is not cosmetic.getAddressFromConfigdecodes anunset value to
address(0x20)and reverts"Address not set"— so a script run before itsdependency has landed stops instead of deploying something wired to
address(0). The fieldsare filled in as each phase lands.
Checked
injective-testnet.json, so no script finds a key missingat deploy time
BaseScript—create3Factory,poolOwnerandprotocolFeeControllerOwnerall resolve to the addresses abovevaultreverts"Address not set", proving the placeholder convention works in thedirection that matters
SCRIPT_CONFIG=injective-mainnet, no broadcast: reads the config, resolvesthe factory, and fails only on the factory not existing yet on 1776 — which is correct
check-fork-pins.shgreeninjectiveis 5 commits ahead ofthe pin
contracts/deployments/*.jsonnames (c53aef3a). Those commits are CI, docs, a licencenotice and one test fix —
src/is byte-identical between the two, so no deployed bytecode isaffected. The fork-pin invariant is all copies of a fork agree with each other, not every pin is
at its fork's HEAD, so nothing is red.
🤖 Generated with Claude Code