Loading
Loading
This page covers deploying a fresh IndexFactory to Robinhood Chain, rehearsing on a fork, and the owner's one job afterwards.
You do not deploy vaults. IndexFactory.launch deploys one per token.
contracts/script/Deploy.s.sol hard-codes every constructor argument:
| Constant | Value |
|---|---|
| Pons factory | 0x7eD598BcEf8bd9Edd8C97A195C6d13f40801EC7e |
| Uniswap v3 factory | 0x1f7d7550B1b028f7571E69A784071F0205FD2EfA |
| SwapRouter02 | 0xCaf681a66D020601342297493863E78C959E5cb2 |
| WETH | 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73 |
| Launch config id | 0 |
| TWAP window | 900 s |
| Max tick deviation | 200 |
| Reward duration | 7 days |
| App fee | 2,000 bps (20%) |
These are immutables. To change one, edit the script and deploy a new factory; the old one and its vaults keep running with the old values.
Before signing anything, the script checks the chain id is 4663, that each address has code, that Pons config 0 is enabled and non-empty, that the fee escrow is set, that a WETH/NVDA 0.3% pool resolves through the v3 factory, and that Pons still approves NVDA as a pair token. After deploying it reads every immutable and the owner back and asserts them. It warns (without failing) if the live launch fee differs from the 0.0005 ETH the web app assumes.
Pick one:
cast wallet import deployer --interactive # encrypted keystore; once
Then pass --account deployer. Or --ledger / --trezor for a hardware wallet. Or PRIVATE_KEY=0x... in the environment, meant for CI.
OWNER is the address that receives Ownable2Step ownership and can call collectAppFees. It defaults to the signer. For mainnet, set it to the treasury multisig:
export OWNER=0x<treasury>
Ownership is set in the constructor. Later transfers use transferOwnership followed by acceptOwnership from the new owner.
contracts/script/deploy-mainnet.sh --account deployer
Builds, runs the fork test suite against live Robinhood Chain, then simulates the deploy. Signs nothing. Prints gas and the address the factory would land on. Add --skip-tests to skip the suite.
OWNER=0x<treasury> contracts/script/deploy-mainnet.sh --account deployer --broadcast --verify
The script prints the target chain and owner and gives you five seconds to abort, then broadcasts with --slow. --verify submits source to Blockscout at robinhoodchain.blockscout.com.
Gas is about 5.6 million; around 0.005 ETH at 0.86 gwei.
On success it prints:
NEXT_PUBLIC_INDEX_FACTORY=<address>, ready to paste into apps/web/.env.local and your hosting provider's environment.It also writes contracts/deployments/4663.json with the address, owner, deployer, every constructor argument, and the block and timestamp. Commit that file. contracts/broadcast/ is gitignored.
The same command is available as bun run contracts:deploy:mainnet -- <flags> from the repo root.
anvil --fork-url <archive rpc> --chain-id 31337
RPC_URL=http://127.0.0.1:8545 PRIVATE_KEY=0x<anvil key> \
contracts/script/deploy-mainnet.sh --fork --broadcast --skip-tests
--fork sets ALLOW_FORK=true so the script accepts a chain id other than 4663. Every preflight check still runs against the forked state. The deployment record is written to contracts/deployments/31337.json; do not commit that one.
Point the web app at the fork as described in Running locally.
NEXT_PUBLIC_INDEX_FACTORY wherever the web app runs and redeploy it.Each harvest sends 20% of its stock to the factory. Those balances sit in the factory until the owner sweeps them.
cast send $FACTORY "collectAppFees(address[],address)" \
"[0xd0601CE157Db5bdC3162BbaC2a2C8aF5320D9EEC,0x<spy>]" 0x<treasury> \
--rpc-url https://rpc.mainnet.chain.robinhood.com --account owner
Pass every stock token you expect a balance in; the call skips zeros. To see what is there first:
cast call 0xd0601CE157Db5bdC3162BbaC2a2C8aF5320D9EEC "balanceOf(address)(uint256)" $FACTORY \
--rpc-url https://rpc.mainnet.chain.robinhood.com
collectAppFees is the owner's only power. The owner cannot change the fee, touch a vault, or affect any launch.
cast send $FACTORY "transferOwnership(address)" 0x<new owner> --rpc-url $RPC --account owner
# then, from the new owner:
cast send $FACTORY "acceptOwnership()" --rpc-url $RPC --account newowner
Until the new owner accepts, the old owner keeps control and can call transferOwnership again to cancel.
canLaunch(address) on the Pons factory decides who may launch. If Pons stops returning true for everyone, ask the Pons owner to whitelist the factory address. No redeploy needed; nothing about the factory changes.