diff --git a/contracts/bridge/script/Install.s.sol b/contracts/bridge/script/Install.s.sol new file mode 100644 index 000000000..27af575b0 --- /dev/null +++ b/contracts/bridge/script/Install.s.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {Vm, VM_ADDRESS} from "../test/Vm.sol"; +import {IgneumCertificateVerifier} from "../src/IgneumCertificateVerifier.sol"; + +/// Installs (or replaces) the voter table on an already deployed verifier (BRIDGE_VERIFIER) from the vectors file in +/// BRIDGE_TABLE_JSON (a gen.mjs table or chain output: keys, weights, index) and, when the file carries a certificate +/// (bitmap, signature), submits it. The deployer key comes from BRIDGE_DEPLOYER_KEY in the environment, never printed. +/// Used for a chain whose table is read at its first lock, after the contract itself was deployed (8 October 2026, +/// igneum-devnet-4: the contract first, the table when the weight window filled). +/// +/// BRIDGE_VERIFIER=0x.. BRIDGE_TABLE_JSON=test/vectors/dn4-table.json forge script script/Install.s.sol:Install --rpc-url sepolia --broadcast --sig "run()" +contract Install { + Vm constant vm = Vm(VM_ADDRESS); + + function run() external { + uint256 key = vm.envUint("BRIDGE_DEPLOYER_KEY"); + IgneumCertificateVerifier v = IgneumCertificateVerifier(vm.envAddress("BRIDGE_VERIFIER")); + string memory j = vm.readFile(vm.envOr("BRIDGE_TABLE_JSON", "test/vectors/dn4-table.json")); + bytes[] memory keys = vm.parseJsonBytesArray(j, ".keys"); + uint256[] memory w = vm.parseJsonUintArray(j, ".weights"); + bytes memory packed; + uint64[] memory weights = new uint64[](w.length); + for (uint256 i = 0; i < keys.length; i++) { + packed = abi.encodePacked(packed, keys[i]); + weights[i] = uint64(w[i]); + } + uint64 index = uint64(vm.parseJsonUint(j, ".index")); + vm.startBroadcast(key); + v.installTable(index, packed, weights); + if (vm.keyExistsJson(j, ".bitmap")) { + v.submitCertificate(index, vm.parseJsonBytes32(j, ".checkpoint"), vm.parseJsonBytes(j, ".bitmap"), vm.parseJsonBytes(j, ".signature")); + } + vm.stopBroadcast(); + } +} diff --git a/docs/contracts/sepolia.json b/docs/contracts/sepolia.json index d2034bc63..337480401 100644 --- a/docs/contracts/sepolia.json +++ b/docs/contracts/sepolia.json @@ -48,6 +48,18 @@ "caveat": "the root is the chain's own but no certificate ties it to a checkpoint (gap 1 in docs/bridge/light-client-bridge.md)" } ] + }, + "IgneumCertificateVerifier_devnet4": { + "address": "0x874D8Be5385474414aeb69EE4AB8374DA34b8c1F", + "create_tx": "0x943b6050602ce0dc9318f1b9a53ed79bf04c1bd9c60a22de2aac65c566f84ecc", + "igneum_chain_id": "igneum-devnet-4", + "evm_chain_id": 4465, + "deployer": "0x70e692A9f1fa1067a8c2d64fDAf1636b4EAEC7e2", + "deployed_at": "2026-10-08T17:2xZ (build-4; build-3 down from 15:40Z with the first deployer key on its disk)", + "table": "not installed yet: devnet-4's voter table is read from igneum_getFinalityWeights at the chain's first finality lock (the 7,200-DAA window filling at about 15 DAA a minute from 2,626 at 16:5xZ, so about 22:00Z) and installed through contracts/bridge/script/Install.s.sol", + "final_checkpoints": "none yet", + "shared_with": "the reference-apps lane's IgneumStateOracle for devnet-4, 0xbb3450049926da3572e6b67cb94df312fe349e34 (setVerifier)", + "note": "Igneum 2.0 (8 October 2026, 17:45 BST): Devnet 3 switched off, igneum-devnet-4 is the 2.0 devnet; the Devnet 3 verifier above keeps its recorded checkpoint and account proof as the record" } }, "first_deploy_note": "A first creation at 0xD7dd375E14F92A4CE4782040325189e6d6E394b6 (tx 0x4db10565\u2026, block 11869633) ran out of gas at Foundry's Prague-spec estimate of 3,323,884; Sepolia runs Osaka pricing (EIP-7883 modexp), so the test EVM and the deploy now use osaka and the RPC's own estimate. That address holds no code.",