Spark Spell 2026-10-08 Security Review

Development Stage Checklist

Preparation

Commits since the last externally reviewed spell

Spell Description & Comments

  • Spell PR has a clear description.
  • Spell PR has a correct spell target date: 2026-10-08
  • Spell contract has a clear description.
  • Spell contract has a correct spell target date.
  • Every significant action and parameter change are clearly commented in the code.
  • Every significant action has valid source url (forum post, poll, atlas).
  • Every parameter change is clearly commented with before/after values.
    • no such comments

Proposed changes

Forum post

[October 8, 2026] Proposed Changes to Spark for Upcoming Spell, https://forum.skyeco.com/t/october-8-2026-proposed-changes-to-spark-for-upcoming-spell/28265

  • Forum post follows the known template.

  • Verify spell content matches the combined scope of the forum posts listed above. From the forum post:

    1. [Arbitrum] Spark Liquidity Layer - Bring the Diamond PAU parallel controller into service on the existing Arbitrum ALM Proxy and open a CCTP V2 USDC route from Arbitrum to Ethereum.
    2. [Arbitrum] Spark Liquidity Layer - Bridge sUSDS from the Ethereum ALM Proxy to the Arbitrum ALM Proxy to replenish the inventory the Arbitrum PSM3 sells. (removed from the spell but present in the forum post)
    3. [Arbitrum] Spark Liquidity Layer - Return idle USDS from Arbitrum to the Ethereum ALM Proxy.
    4. [X Layer] Spark Savings - Add spUSDC to the X Layer Savings Vault Intents contract and make the spUSDC PAU Administered Agent a relayer on it.
    5. [Arbitrum] Spark Liquidity Layer - Grant the PAS Configurator admin over the Arbitrum Diamond PAU access controls and rate limits.
    6. [Arbitrum] Spark Liquidity Layer - Transfer admin of the Arbitrum Diamond PAU Beacon from the Spark Executor to the Sky governance relay.
    7. [Ethereum] SparkLend - Claim accrued SparkLend reserves and route them to the Spark Liquidity Layer and the Spark Operations Multisig (recurring).

    From SparkArbitrumOne_20261008.sol:

    @notice Spark Liquidity Layer:
      - Onboard Parallel Diamond PAU with CCTP V2.
      - Return idle USDS from Arbitrum to the Ethereum ALM Proxy.
      - Grant the PAS Configurator admin over the Arbitrum Diamond PAU access controls and rate limits.
      - Transfer admin of the Arbitrum Diamond PAU Beacon from the Spark Executor to the Sky governance relay.

    From SparkXLayer_20261008.sol:

    @notice Spark Savings Intents:
      - Add spUSDC to the X Layer Savings Vault Intents contract.
      - Make the spUSDC PAU Administered Agent a relayer on Savings Intents contract.

    [Ethereum] SparkLend — Claim accrued SparkLend reserves (…) is a part of the execution process.

  • Verify forum posts contain all new addresses directly or indirectly used in the spell, their constructor arguments and rate limits.

  • IF the Prime Agent spell introduces a major change that can affect external parties, suggest the Core Facilitator to set Core Spell office hours to true.

Contract Structure & Code Quality

  • The only external non-view function in the spell contract is execute().
  • There are no methods that can modify contract state after deployment.
  • No unused imports, interfaces, methods, or variables.
  • All function visibility modifiers are explicitly declared.
  • No redundant code or commented-out functionality.
  • Addresses must be fetched from spark-address-registry IF they are present there, OTHERWISE defined as constant and have trusted source (e.g., when onboarding new contracts).

Every address used in the spell

  • [ArbitrumOne] PAS_CONFIGURATOR 0xd11Dc57F3eF23bb7b3142588a461F68460a7C474

    • Matches valid external source. (forum post)
  • [ArbitrumOne] SOTER_FREEZER_MULTISIG 0x747BF29B189e2a070a921Af7Cf65681E3d5F5967

    • Matches valid external source. (forum post)
  • [ArbitrumOne] SOTER_GRANTOR_MULTISIG 0x97EC6398e5dD047BA3223cFC017bFC6436Ac3Fe7

    • Matches valid external source. (forum post)
  • [ArbitrumOne] SPARK_HOT_WALLET 0x062cE42caE04c51D04E77e3D64cc8953a2296FfE

    • Matches valid external source. (forum post)
  • [ArbitrumOne] Arbitrum.ALM_PROXY

    • Matches valid external source (spark-address-registry/Arbitrum.sol)
  • [ArbitrumOne] Arbitrum.PAU_CONTROLLER

    • Matches valid external source (spark-address-registry/Arbitrum.sol)
  • [ArbitrumOne] Arbitrum.PAU_ADMINISTERED_AGENT

    • Matches valid external source (spark-address-registry/Arbitrum.sol)
  • [ArbitrumOne] Arbitrum.PAU_GRANTOR_MULTISIG

    • Matches valid external source (spark-address-registry/Arbitrum.sol)
  • [ArbitrumOne] Arbitrum.PAU_RATELIMITS

    • Matches valid external source (spark-address-registry/Arbitrum.sol)
  • [ArbitrumOne] Ethereum.ALM_PROXY

    • Matches valid external source (spark-address-registry/Ethereum.sol)
  • [ArbitrumOne] Arbitrum.USDS

    • Matches valid external source (spark-address-registry/Arbitrum.sol)
  • [ArbitrumOne] Arbitrum.PAU_ACCESS_CONTROLS

    • Matches valid external source (spark-address-registry/Arbitrum.sol)
  • [ArbitrumOne] Arbitrum.SPARK_BEACON

    • Matches valid external source (spark-address-registry/Arbitrum.sol)
  • [ArbitrumOne] Arbitrum.SKY_GOV_RELAY

    • Matches valid external source (spark-address-registry/Arbitrum.sol)
  • [ArbitrumOne] Arbitrum.SPARK_EXECUTOR

    • Matches valid external source (spark-address-registry/Arbitrum.sol)
  • [ArbitrumOne] Arbitrum.TOKEN_BRIDGE

    • Matches valid external source (spark-address-registry/Arbitrum.sol)
  • [XLayer] XLayer.SPARK_SAVINGS_INTENTS

    • Matches valid external source (spark-address-registry/XLayer.sol)
  • [XLayer] XLayer.SPARK_VAULT_V2_SPUSDC

    • Matches valid external source (spark-address-registry/XLayer.sol)
  • [XLayer] XLayer.SPUSDC_PAU_ADMINISTERED_AGENT

    • Matches valid external source (spark-address-registry/XLayer.sol)

StarGuard execution

  • IF a StarGuard module is onboarded for this Prime Agent, the following additional checks are done:
    • The spell exposes view-only interface function isExecutable() external view returns (bool result).
    • isExecutable either simply returns true or implements additional logic communicated via the relevant forum post (e.g., by describing “earliest launch date” or “office hours” logic, etc).
    • The test ensures the spell is executable before expiration (i.e. isExecutable outputs true before StarGuard.maxDelay() is passed).
    • Third-party actors can not take advantage of the fact that Spell will be executed in a later block than the Core spell, otherwise suggest direct execution.
    • IF Prime Agent spell can not be executed in a later block OR have to be executed sequentially to another Prime Agent spell, direct execution is clearly mentioned in the forum post together with elaborated explanation why it is needed.
    • The direct execution explanation makes sense on the technical level and can not be circumvented by the use of isExecutable() interface.

On-boarding New Contracts

Deployment verification for Arbitrum’s PAU stack contracts (PAU_ACCESS_CONTROLS, PAU_RATELIMITS, SPARK_BEACON, PAU_CONTROLLER, and PAU_ADMINISTERED_AGENT) was completed as part of our report: https://portfolio.unvariant.io/reports/spark/spark-cctpv2-dual-controller/

PAS_CONFIGURATOR

Bytecode verification
BeamState state

Wards

  • wards[Arbitrum.SKY_GOV_RELAY] = 1
  • wards[L2PASDeployer(0x6547c342ED83b6dEEf9Ac7525fc1196F7Bfa5A4D)] = 0

userRoles

Global config

  • hop[address(0)] (general fallback) = 57600 (= 16 hours)
  • maxChange[address(0)] (general fallback) = 1.2e18 (×1.2 WAD growth cap)

Registries

  • rateLimits[Arbitrum.PAU_RATELIMITS] = 1
  • controllers[Arbitrum.PAU_CONTROLLER] = 1
  • cBeams[PAS_CBEAM(0x492aae70E59551768BAF3c7159d3f951B6ed76Fe)] = 1
  • rateLimitsCBeams[Arbitrum.PAU_RATELIMITS][PAS_CBEAM] = 1
  • controllersCBeams[Arbitrum.PAU_CONTROLLER][PAS_CBEAM] = 1

Init / pre-approved data

  • initControllerActions[keccak256(removeIntegrations([bytes32("CCTP_FACET")]))][Arbitrum.PAU_CONTROLLER] = 1
  • initRateLimits: none
Timelock state

Roles

Global config

  • paused() = true
  • getMinDelay() = 1209600
  • getOperationsCount() = 0

SPARK_SAVINGS_INTENTS

Bytecode verification
State and roles

SPUSDC_PAU_ADMINISTERED_AGENT

Bytecode verification
State and roles

Dependency checks

Interfaces

  • No unused static interfaces.
  • Declared static interface is not present in standard libraries, OTHERWISE should be imported from there.
  • Interface matches the deployed contract.
  • Each static interface declares only functions actually used in the spell code.

Variable Declarations

  • Every contract variable is declared as either constant or immutable.

  • Every precision variable (WAD, RAY, RAD, etc) match their expected value. - No precision variable declared. Variables using precision (e18, e6, e..., WAD, RAY, RAD, etc): SparkArbitrumOne_20261008.sol:

    • setRateLimitData maxAmount: 5_000_000e6 with precision 6
      • The precision matches provided source url. - USDC has 6 decimals
    • setRateLimitData slope: uint256(50_000_000e6) / 1 days with precision 6
      • The precision matches provided source url. - USDC has 6 decimals

    SparkXLayer_20261008.sol:

    • updateVaultConfig minIntentAssets_ and maxIntentAssets_: 1_000_000e6, 500_000_000e6 both use precision 6
      • The precision matches provided source url. - spUSDC asset is USDC, 6 decimals
  • Rates are expressed correctly (e.g. per / 1 days). - yes, only 1 rate used: in [Arbitrum]IRateLimitsLike(Arbitrum.PAU_RATELIMITS).setRateLimitData the slope value is uint256(50_000_000e6) / 1 days

  • Rates match their source (e.g., governance poll). - Forum Item 1: 5,000,000 USDC maximum at 50,000,000 USDC per day

  • Timestamps are commented with the full UTC date and convert correctly. - No timestamps in the spell.

  • Timestamps match their source (e.g., governance poll). - No timestamps in the spell.

Deployment & Execution Security

  • No selfdestruct() operations in the spell.
  • No delegatecall() to untrusted contracts.
  • No use of tx.origin for authorization.
  • No external calls that could revert and fail the entire spell execution.
  • No loops with unbounded gas consumption.
  • No timestamp-dependent logic that could cause issues across the GSM delay.
  • All math operations use safe math libraries or are checked for overflow/underflow.
  • No unchecked return values from external calls.
    • SparkArbitrumOne_20261008._sendUSDSBackFromArbitrum() contains calls which have unchecked return values, but it’s fine here since all failure paths revert

Access Control

  • Spell execution cannot be front-run by malicious actors.
  • No privileged functions accessible by unauthorized users.

Parameter Changes & Protocol Integration

  • Prime Agent protocol invariants are maintained after spell execution.
  • All parameter changes use the appropriate helper functions IF available.
  • Parameter changes match the governance record applicable to this Prime Agent Spell exactly: the corresponding Atlas edit weekly proposal (Sky-governed), or the proposal forum post and Snapshot vote (self-governed, for changes to the Prime Agent’s own artifact).
  • Spell interacts correctly with existing protocol components.
  • Proper error handling for all external interactions.

Testing

All spell actions :

  • “Onboard Parallel Diamond PAU with CCTP V2.” tested via test_ARBITRUM_sll_parallelPAU_roles(), test_ARBITRUM_sll_parallelPAU_roles_events(), test_ARBITRUM_sll_pauCctpV2_onboarding(), test_ARBITRUM_sll_pauCctpV2_rateLimitEnforced(), test_ARBITRUM_sll_soterMultisigs_threshold(), test_E2E_sparkLiquidityLayerCCTPCrossChainSetup()
    • The unit test ensures the new value was changed in the spell.
    • The end-to-end test is sufficient to ensure correctness the high-level goal behind this spell action.
  • “Return idle USDS from Arbitrum to the Ethereum ALM Proxy.” tested via test_ARBITRUM_sll_removeExcessLiquidity()
    • The unit test ensures the new value was changed in the spell.
    • The end-to-end test is sufficient to ensure correctness the high-level goal behind this spell action.
  • “Grant the PAS Configurator admin over the Arbitrum Diamond PAU access controls and rate limits.” tested via test_ARBITRUM_sll_parallelPAU_grantPASConfigurator(), test_ARBITRUM_pasConfigurator_setRateLimit(), test_ARBITRUM_sll_pasConfigurator_callControllerAction(), test_ARBITRUM_beamState_unsetCBeam_revokesConfiguratorAccess(), test_ARBITRUM_beamState_stop()
    • The unit test ensures the new value was changed in the spell.
    • The end-to-end test is sufficient to ensure correctness the high-level goal behind this spell action.
  • “Transfer admin of the Arbitrum Diamond PAU Beacon from the Spark Executor to the Sky governance relay.” tested via test_ARBITRUM_sll_beaconRoleTransfer()
    • The unit test ensures the new value was changed in the spell.
    • The end-to-end test is sufficient to ensure correctness the high-level goal behind this spell action.
  • “Add spUSDC to the X Layer Savings Vault Intents contract.” tested via test_XLAYER_savingsIntents_spUSDC_updateVaultConfig(), test_XLAYER_savingsIntents_spUSDC_e2e()
    • The unit test ensures the new value was changed in the spell.
    • The end-to-end test is sufficient to ensure correctness the high-level goal behind this spell action.
  • “Make the spUSDC PAU Administered Agent a relayer on Savings Intents contract.” tested via test_XLAYER_savingsIntents_grantRole(), test_XLAYER_savingsIntents_spUSDC_e2e()
    • The unit test ensures the new value was changed in the spell.
    • The end-to-end test is sufficient to ensure correctness the high-level goal behind this spell action.
  • All actions are covered by tests.
  • Integration tests verify the end-to-end execution flow.
  • Gas tests ensure execution is possible within the existing block gas limit.
    • no such test
  • All tests are passing in CI at bebba1f485f213287d4825f54b4987bd387468db.
  • All tests listed above are not skipped.
  • All tests are passing locally at bebba1f485f213287d4825f54b4987bd387468db:

Deployment Stage Checklist

Deployed Contract

  •  Both reviewers gave explicit “Good to deploy”.
  •  A new comment in the PR contains link to the deployed spell(s) and Tenderly vnet(s).
  •  The comment also contains codehash of the deployed mainnet spell.
  •  The codehash matches one produced locally from the reviewed source code.
❯ cast call --rpc-url $ETH_RPC --create $(forge inspect SparkEthereum_20261008 bytecode) | cast keccak
0x06af8f55b18ae1bb19a13b9cd3531a164a53da94db01586499d9d2a22009cddb
❯ cast code 0x796eE21eb57C8BE71be7F75770f534D249bC555b --rpc-url $ETH_RPC | cast keccak
0x06af8f55b18ae1bb19a13b9cd3531a164a53da94db01586499d9d2a22009cddb

❯ cast call --rpc-url $ARB_RPC --create $(forge inspect SparkArbitrumOne_20261008 bytecode) | cast keccak
0xea90cd0c2c0cf1a92f4aacd14fe3a30b867514ce152bcf97b0dc34ff6e62ade4
❯ cast code 0xb037C43b433964A2017cd689f535BEb6B0531473 --rpc-url $ARB_RPC | cast keccak
0xea90cd0c2c0cf1a92f4aacd14fe3a30b867514ce152bcf97b0dc34ff6e62ade4

❯ cast call --rpc-url https://rpc.xlayer.tech --create $(forge inspect SparkXLayer_20261008 bytecode) | cast keccak
0xc5051f9572826f58bfd219549004a7c318208b84208b86e82cd595713e492b2f
❯ cast code 0x3c2B7d559Fd4bd17827B49278FCe1c7d55f39311 --rpc-url https://rpc.xlayer.tech | cast keccak
0xc5051f9572826f58bfd219549004a7c318208b84208b86e82cd595713e492b2f
❯ forge test
[⠒] Compiling...
No files changed, compilation skipped

Ran 17 tests for src/proposals/20261008/Spell_20261008.t.sol:SparkEthereum_20261008_SpellTests
[PASS] test_ARBITRUM_ONE_PayloadBytecodeMatches() (gas: 724781)
[PASS] test_ARBITRUM_sll_soterMultisigs_threshold() (gas: 87128)
[SKIP] test_AVALANCHE_PayloadBytecodeMatches() (gas: 0)
[SKIP] test_BASE_PayloadBytecodeMatches() (gas: 0)
[PASS] test_ETHEREUM_PayloadBytecodeMatches() (gas: 2196006)
[PASS] test_ETHEREUM_PayloadsConfigured() (gas: 77527)
[PASS] test_ETHEREUM_SparkProxyStorage() (gas: 62215622)
[PASS] test_ETHEREUM_sparkLend_withdrawAllReserves() (gas: 64053945)
[SKIP] test_GNOSIS_PayloadBytecodeMatches() (gas: 0)
[SKIP] test_OPTIMISM_PayloadBytecodeMatches() (gas: 0)
[SKIP] test_ROBINHOOD_PayloadBytecodeMatches() (gas: 0)
[SKIP] test_UNICHAIN_PayloadBytecodeMatches() (gas: 0)
[PASS] test_XLAYER_PayloadBytecodeMatches() (gas: 169417)
[PASS] test_XLAYER_savingsIntents_grantRole() (gas: 61994821)
[PASS] test_XLAYER_savingsIntents_spUSDC_e2e() (gas: 82916207)
[PASS] test_XLAYER_savingsIntents_spUSDC_updateVaultConfig() (gas: 61985498)
[PASS] test_officeHours() (gas: 55368)
Suite result: ok. 11 passed; 0 failed; 6 skipped; finished in 268.54s (835.25ms CPU time)

Warning: the following cheatcode(s) are deprecated and will be removed in future versions:
  snapshot(): replaced by `snapshotState`
  revertTo(uint256): replaced by `revertToState`
Ran 15 tests for src/proposals/20261008/Spell_20261008.t.sol:SparkEthereum_20261008_SparklendTests
[PASS] test_ETHEREUM_AllReservesSeeded() (gas: 62292463)
[PASS] test_ETHEREUM_CapAutomator() (gas: 88860136)
[PASS] test_ETHEREUM_E2E_sparkLend() (gas: 3860550132)
[PASS] test_ETHEREUM_EModePriceSources() (gas: 71283586)
[PASS] test_ETHEREUM_FreezerMom() (gas: 189470971)
[PASS] test_ETHEREUM_FreezerMom_Multisig() (gas: 151324596)
[PASS] test_ETHEREUM_Oracles() (gas: 64052608)
[PASS] test_ETHEREUM_RewardsConfiguration() (gas: 63063060)
[PASS] test_ETHEREUM_SpellExecutionDiff() (gas: 286883194)
[PASS] test_ETHEREUM_TokenImplementationsMatch() (gas: 62525192)
[SKIP] test_GNOSIS_AllReservesSeeded() (gas: 0)
[SKIP] test_GNOSIS_E2E_sparkLend() (gas: 0)
[SKIP] test_GNOSIS_Oracles() (gas: 0)
[SKIP] test_GNOSIS_SpellExecutionDiff() (gas: 0)
[SKIP] test_GNOSIS_TokenImplementationsMatch() (gas: 0)
Suite result: ok. 10 passed; 0 failed; 5 skipped; finished in 285.90s (18.27s CPU time)

Warning: the following cheatcode(s) are deprecated and will be removed in future versions:
  snapshot(): replaced by `snapshotState`
  revertTo(uint256): replaced by `revertToState`
Ran 38 tests for src/proposals/20261008/Spell_20261008.t.sol:SparkEthereum_20261008_SLLTests
[PASS] test_ARBITRUM_E2E_sparkLiquidityLayer() (gas: 777220711)
[PASS] test_ARBITRUM_beamState_actionRoles() (gas: 416557)
[PASS] test_ARBITRUM_beamState_cBeams() (gas: 66851)
[PASS] test_ARBITRUM_beamState_controllers() (gas: 66805)
[PASS] test_ARBITRUM_beamState_controllersCBeams() (gas: 67921)
[PASS] test_ARBITRUM_beamState_delCBeam_onlyCouncil() (gas: 45406)
[PASS] test_ARBITRUM_beamState_hop() (gas: 60804)
[PASS] test_ARBITRUM_beamState_initControllerActions() (gas: 71328)
[PASS] test_ARBITRUM_beamState_initRateLimits() (gas: 55565)
[PASS] test_ARBITRUM_beamState_maxChange() (gas: 60659)
[PASS] test_ARBITRUM_beamState_rateLimits() (gas: 66828)
[PASS] test_ARBITRUM_beamState_rateLimitsCBeams() (gas: 73150)
[PASS] test_ARBITRUM_beamState_setHop_onlyTimelock() (gas: 352004)
[PASS] test_ARBITRUM_beamState_stop() (gas: 62234645)
[PASS] test_ARBITRUM_beamState_stopped() (gas: 66630)
[PASS] test_ARBITRUM_beamState_unsetCBeam_revokesConfiguratorAccess() (gas: 62168416)
[PASS] test_ARBITRUM_beamState_userRoles() (gas: 75024)
[PASS] test_ARBITRUM_beamState_wards() (gas: 102628)
[PASS] test_ARBITRUM_pasConfigurator_setRateLimit() (gas: 62354460)
[PASS] test_ARBITRUM_pasConfigurator_state() (gas: 27619)
[PASS] test_ARBITRUM_sll_beaconRoleTransfer() (gas: 62054570)
[PASS] test_ARBITRUM_sll_parallelPAU_grantPASConfigurator() (gas: 62061839)
[PASS] test_ARBITRUM_sll_parallelPAU_roles() (gas: 62093232)
[PASS] test_ARBITRUM_sll_parallelPAU_roles_events() (gas: 60609809)
[PASS] test_ARBITRUM_sll_pasConfigurator_callControllerAction() (gas: 62318936)
[PASS] test_ARBITRUM_sll_pauCctpV2_onboarding() (gas: 62101699)
[PASS] test_ARBITRUM_sll_pauCctpV2_rateLimitEnforced() (gas: 62067163)
[PASS] test_ARBITRUM_sll_removeExcessLiquidity() (gas: 69064918)
[PASS] test_ARBITRUM_timelock_events() (gas: 219257)
[PASS] test_ARBITRUM_timelock_state() (gas: 61060)
[PASS] test_AVALANCHE_E2E_sparkLiquidityLayer() (gas: 312873040)
[PASS] test_BASE_E2E_sparkLiquidityLayer() (gas: 618149150)
[PASS] test_E2E_sparkLiquidityLayerCCTPCrossChainSetup() (gas: 4823772534)
[PASS] test_ETHEREUM_E2E_sparkLiquidityLayer() (gas: 2169789900)
[PASS] test_OPTIMISM_E2E_sparkLiquidityLayer() (gas: 400215565)
[PASS] test_UNICHAIN_E2E_sparkLiquidityLayer() (gas: 365302313)
[PASS] test_XLAYER_sll_cctp_e2e_roundTrip() (gas: 2298672)
[PASS] test_XLAYER_spUsdcAdministeredAgent_roles() (gas: 54363)
Suite result: ok. 38 passed; 0 failed; 0 skipped; finished in 306.59s (211.88s CPU time)

Ran 3 test suites in 306.62s (861.03s CPU time): 59 tests passed, 0 failed, 11 skipped (70 total tests)

Simulation Checks

Spell Caster comment posted 2026-10-06 12:18 UTC from 340632eee12967c183d9bdda2c3af51d62d7ca44:

  1. Arbitrum vnet: https://virtual.arbitrum.eu.rpc.tenderly.co/65ccd0b5-7d5d-4436-9c08-a7723c986f34
  2. Ethereum vnet: https://virtual.mainnet.eu.rpc.tenderly.co/5c886ee8-fe31-4cf1-a6e0-0b81474dabee
  • The Tenderly simulation shows all actions are executed successfully.
    • Ethereum: tx 0xcfd6b1e607296d4ca2277e282bb082b27be46e3790298fe03de79d0859925b55, SPARK_PROXY.exec(payload) from the pause proxy, status 1, 3,419,441 gas, 96 logs: Arbitrum retryable created (Bridge MessageDelivered, Inbox InboxMessageDelivered), X Layer message sent (OptimismPortal TransactionDeposited, L1CrossDomainMessenger SentMessage), then the recurring reserve claim: 11 MintedToTreasury (the 11 reserves with non-zero accrual) and spToken transfers to the ALM Proxy / Ops Multisig. Post-state: accruedToTreasury == 0 on all 20 reserves; SPARK_PROXY ETH down by 0.05 ETH (retryable funding).
    • Arbitrum: tx 0x2045fb80331131cea922aa81f1826cb23075174c236f581a22cdab6eaf05eda5, Executor.execute, status 1, 782,249 gas, 20 logs in payload order: ALM Proxy RoleGranted(CONTROLLER, PAU_CONTROLLER); agent RevokerAdded, GrantorAdded, GrantorRemoved, ActorAdded; PAU RateLimits RateLimitDataSet x2; PAU Controller CCTPDomainParametersSet; ALM Proxy RoleGranted(CONTROLLER, Executor); USDS Approval, Transfer (burn 99,326,272.78); ArbSys L2ToL1Tx; gateway TxToL1, WithdrawalInitiated; ALM Proxy RoleRevoked; AccessControls RoleGranted(0x00, Configurator); RateLimits RoleGranted(0x00, Configurator); Beacon RoleGranted(0x00, SKY_GOV_RELAY), RoleRevoked(0x00, Executor); Executor ActionsSetExecuted. Post-state read from the vnet: PAU Controller and legacy controller both hold CONTROLLER, Executor does not; agent 1/2/1/2 with hot wallet, Soter grantor, Soter freezer; aggregate key unlimited, domain-0 key 5,000,000e6 / 578,703,703 per second; domain 0 recipient = Ethereum ALM Proxy; ALM Proxy USDS 0, allowance 0; Configurator admin on AccessControls (count 2) and RateLimits; Beacon admin count 1 = SKY_GOV_RELAY.
  • The Tenderly simulation shows no extra actions not present in the spell are executed.
    • Every one of the 20 Arbitrum events and 96 Ethereum events maps to a payload line or to the inherited reserve claim. The three Arbitrum setup transactions (grantRole(SUBMISSION_ROLE, 0x0), updateDelay(0), queue(...) from 0x0) are Spell Caster scaffolding that stands in for the retryable -> Receiver path; they are not spell actions.
  • The Tenderly simulation shows no reverts or out-of-gas errors.
  • IF no blockers were found, post the completed “Deployment Stage” checklist stage with the explicit “Good to handover” note on top.

Handover Stage

Confirmed Handover

  • Both reviewers gave explicit “Good to handover”.
  • All review comments have been addressed or resolved.
  • The spell handover message is posted by the crafter in the existing spell thread in the #govops Slack channel using the applicable format:
    • IF direct execution is no: Whitelist Spark spell with address 0x796eE21eb57C8BE71be7F75770f534D249bC555b and codehash 0x06af8f55b18ae1bb19a13b9cd3531a164a53da94db01586499d9d2a22009cddb in STARGUARD, direct execution: No
    • IF direct execution is yes: Execute the <StarName> Proxy Spell at 0x…
  • Posted spell address matches spell address approved for handover.
  • IF the message includes a codehash, it matches the codehash verified locally.
  • The selected message format matches the direct execution value in the forum post.
  • Confirm the address (via a separate “reply to” message, restating the address to avoid edits).
  • Confirm that no changes have been made to the code since the “Good to deploy” comment was posted, EXCEPT for changes related to deployment. (i.e. adding the deployed spell payload, updating test code to use the deployed contract for testing).
  • IF no blockers were found, post the completed “Handover Stage” checklist stage with the explicit pull request approval via ‘Approve’ review option.