0x2723723f…0411sent to0xbeccb6bb…9bf6·#25,546,393·view on Etherscan
transferOwnership(address)# Shut Down the sINV CCIP Bridge Lanes
Forum: https://forum.inverse.finance/t/shut-down-the-sinv-ccip-bridge-lanes/669
## Summary
This proposal closes the idle sINV Chainlink CCIP integration by de-allowlisting every cross-chain lane, in both directions, on all five sINV bridge contracts: the two mainnet `ProgrammableDataTokenTransfers` deployments (old and new) and the three L2 bridges on Base, Optimism, and Arbitrum.
The L2-side lane removals are batched through `SINVBridgeShutdownGovernor`, a purpose-built contract that fires all 30 cross-chain shutdown messages in a single `executeL2Shutdown()` call. The mainnet-side lane removals are executed as direct proposal actions.
Ownership of the sINV `GovernanceSender` and of every pool remains with the DAO governance timelock throughout, and is returned to it as the final step.
## Rationale
The sINV CCIP integration is not currently in use. Monitoring shows no live cross-chain activity and no deposits. While idle, leaving the bridge lanes open is an unnecessary risk surface.
The safe configuration when idle is to close every lane at both ends. Removing the outbound (destination-chain) allowlist on each contract prevents any new transfer from being initiated, and removing the inbound (source-chain) allowlist on each contract rejects any message that nonetheless arrives. Closing only one side would let a user initiate a transfer that then cannot be delivered, stranding funds mid-flight.
## The Shutdown Governor
`SINVBridgeShutdownGovernor` (`0xb10D422b53789D570bAFE2f7145c1f6aeDF4a133`) dispatches every L2 shutdown message from a single `executeL2Shutdown()` entrypoint. It is `onlyOwner` (owner = the DAO governance timelock) and `payable`, with forwarded ETH paying the CCIP message fees, and it holds a hardcoded `L2_SHUTDOWN_MESSAGE_COUNT = 30`.
The governor can only act once it owns the sINV `GovernanceSender` (`0xAeA8Ae87A34a0fAaEa0e6beD9f4627F576B524Fa`), the allowlisted origin for the cross-chain messages. The proposal therefore transfers the `GovernanceSender` to the governor, calls `executeL2Shutdown()`, recovers unspent fees, then transfers the `GovernanceSender` back to the timelock.
The 30 messages break down as ten per L2 bridge:
- `allowlistDestinationChain(remote, false)` for each of the other two L2s plus mainnet (3 messages)
- `allowlistSourceChain(remote, false)` for each of the other two L2s plus mainnet (3 messages)
- `allowlistSender(bridge, selector, false)` for both mainnet bridges plus the two other L2 bridges (4 messages)
Ten messages across three L2 bridges gives thirty total, matching the hardcoded count.
The mainnet pools are shut down separately, as direct actions, because the timelock owns them and no batching contract is needed. The governor's `withdraw(beneficiary)` recovers unspent CCIP fees and is executed while the governor still owns the `GovernanceSender`.
## Configuration
Chain selectors:
| Chain | Selector |
|---|---|
| Ethereum | `5009297550715157269` |
| Base | `15971525489660198786` |
| Optimism | `3734403246176062136` |
| Arbitrum | `4949039107694359620` |
Contract addresses:
| Contract | Address |
|---|---|
| SINVBridgeShutdownGovernor | `0xb10D422b53789D570bAFE2f7145c1f6aeDF4a133` |
| GovernanceSender (sINV) | `0xAeA8Ae87A34a0fAaEa0e6beD9f4627F576B524Fa` |
| DAO governance timelock (owner) | `0x926dF14a23BE491164dCF93f4c468A50ef659D5B` |
sINV ProgrammableDataTokenTransfers contracts (the CCIP token pools, not the L2 sINV tokens):
| Chain | Token Pool |
|---|---|
| Ethereum (new) | `0x70F3795c1EF726c58FfeA2e1A51526ac5707C066` |
| Ethereum (old) | `0x7A43C13f7Fb3A0bF19cEB3fBC583A0CAda6D29a2` |
| Base | `0x0173804066F7403E0815680F3DDa125a6cd10F7c` |
| Optimism | `0xb5A998E90AdeD2C97f7ceDbb7c45Bbc27E82dfdD` |
| Arbitrum | `0x1230bd56bf23Bf7adF95b9F861711301E3CCd6b3` |
L2 governance proxies (CCIP message receivers; they receive each cross-chain message and forward to the explicit target):
| Chain | sINV proxy |
|---|---|
| Base | `0x5D5392505ee69f9FE7a6a1c1AF14f17Db3B3e364` |
| Optimism | `0xCbB162B761B83578b2a0226cbAf4C1adE0d60B2e` |
| Arbitrum | `0x1230bd56bf23Bf7adF95b9F861711301E3CCd6b3` |
## On-Chain Actions
Ownership of the `GovernanceSender` moves via Chainlink's two-step `ConfirmedOwner` pattern. The `GovernanceSender`'s leftover-fee sweep only succeeds while the governor still owns it, so the fee recovery (action 4) sits after `executeL2Shutdown()` and before ownership is handed back.
| # | Target | Function | Value | Calldata (arguments) |
|---|---|---|---|---|
| 1 | GovernanceSender `0xAeA8Ae87A34a0fAaEa0e6beD9f4627F576B524Fa` | `transferOwnership(address)` | 0 | `0xb10D422b53789D570bAFE2f7145c1f6aeDF4a133` |
| 2 | Governor `0xb10D422b53789D570bAFE2f7145c1f6aeDF4a133` | `acceptGovernanceSenderOwnership()` | 0 | `0x` |
| 3 | Governor `0xb10D422b53789D570bAFE2f7145c1f6aeDF4a133` | `executeL2Shutdown()` | **CCIP fees** | `0x` *(fires 30 L2 messages)* |
| 4 | Governor `0xb10D422b53789D570bAFE2f7145c1f6aeDF4a133` | `withdraw(address)` | 0 | `0x926dF14a23BE491164dCF93f4c468A50ef659D5B` |
| 5 | Governor `0xb10D422b53789D570bAFE2f7145c1f6aeDF4a133` | `transferGovernanceSenderOwnership(address)` | 0 | `0x926dF14a23BE491164dCF93f4c468A50ef659D5B` |
| 6 | GovernanceSender `0xAeA8Ae87A34a0fAaEa0e6beD9f4627F576B524Fa` | `acceptOwnership()` | 0 | `0x` |
| 7 | OLD PDTT `0x7A43C13f7Fb3A0bF19cEB3fBC583A0CAda6D29a2` | `acceptOwnership()` | 0 | `0x` |
| 8 | OLD PDTT `0x7A43C13f7Fb3A0bF19cEB3fBC583A0CAda6D29a2` | `allowlistDestinationChain(uint64, bool)` | 0 | `15971525489660198786, false` |
| 9 | OLD PDTT `0x7A43C13f7Fb3A0bF19cEB3fBC583A0CAda6D29a2` | `allowlistDestinationChain(uint64, bool)` | 0 | `3734403246176062136, false` |
| 10 | OLD PDTT `0x7A43C13f7Fb3A0bF19cEB3fBC583A0CAda6D29a2` | `allowlistDestinationChain(uint64, bool)` | 0 | `4949039107694359620, false` |
| 11 | OLD PDTT `0x7A43C13f7Fb3A0bF19cEB3fBC583A0CAda6D29a2` | `allowlistSourceChain(uint64, bool)` | 0 | `15971525489660198786, false` |
| 12 | OLD PDTT `0x7A43C13f7Fb3A0bF19cEB3fBC583A0CAda6D29a2` | `allowlistSourceChain(uint64, bool)` | 0 | `3734403246176062136, false` |
| 13 | OLD PDTT `0x7A43C13f7Fb3A0bF19cEB3fBC583A0CAda6D29a2` | `allowlistSourceChain(uint64, bool)` | 0 | `4949039107694359620, false` |
| 14 | NEW PDTT `0x70F3795c1EF726c58FfeA2e1A51526ac5707C066` | `allowlistDestinationChain(uint64, bool)` | 0 | `15971525489660198786, false` |
| 15 | NEW PDTT `0x70F3795c1EF726c58FfeA2e1A51526ac5707C066` | `allowlistDestinationChain(uint64, bool)` | 0 | `3734403246176062136, false` |
| 16 | NEW PDTT `0x70F3795c1EF726c58FfeA2e1A51526ac5707C066` | `allowlistDestinationChain(uint64, bool)` | 0 | `4949039107694359620, false` |
| 17 | NEW PDTT `0x70F3795c1EF726c58FfeA2e1A51526ac5707C066` | `allowlistSourceChain(uint64, bool)` | 0 | `15971525489660198786, false` |
| 18 | NEW PDTT `0x70F3795c1EF726c58FfeA2e1A51526ac5707C066` | `allowlistSourceChain(uint64, bool)` | 0 | `3734403246176062136, false` |
| 19 | NEW PDTT `0x70F3795c1EF726c58FfeA2e1A51526ac5707C066` | `allowlistSourceChain(uint64, bool)` | 0 | `4949039107694359620, false` |