Nonceworks

Superfluid moved TOGA on six chains; the metadata still points at the old contracts

Written 17 October 2026

Written 2026-10-17 for anyone who runs superfluid-sentinel, holds a PIC seat, or reads TOGA state on Gnosis, Polygon, Optimism, Arbitrum, Avalanche or BNB Chain. Base, Ethereum, Celo, Scroll and Arc are not affected.

Upstream issue: superfluid-org/protocol-monorepo #2243, filed 2026-10-17 with a fix to the metadata.

What changed

When an account is closed inside the patrician window, Superfluid pays the liquidation reward to the token's reward address. That address is a TOGA contract, and the reward joins the bond of whoever holds the token's seat there, the PIC. Governance decides which contract it is.

On 2026-09-10, between 12:38 and 12:45 UTC, Superfluid's governance Safe set a new default reward address on six chains, one transaction per chain. Each new address is a TOGA deployed on 2026-09-08. All six run the same TOGA v3 code. Where it is verified (Gnosis and Optimism on their explorers; Gnosis, Polygon, Arbitrum and Avalanche on Sourcify), the source is identical to TOGA.sol in Superfluid's monorepo as of #2097 (a5bf3a6); the current dev version has since gained bond(). For every token we checked, 5 to 30 per chain, the reward address is now the new contract, and according to Superfluid's subgraph no reward has been paid to the old contracts since the change.

TOGA has no admin functions, so the new contracts started with no PICs. A seat on an old contract did not carry over, and it earns nothing now. Rewards that land while a seat has no PIC become part of the first bidder's bond.

Chain Old TOGA (still in metadata) New TOGA (reward address) Changed at block (UTC)
Gnosis 0xb7DE52F4281a7a276E18C40F94cd93159C4A2d22 0x177Ab68dc7B0032Fce7d64d5BD28a5983bD42B3B 48,178,651, 12:38:55
Polygon 0x6AEAeE5Fd4D05A741723D752D30EE4D72690A8f7 0xeF3cB64Ab9021E400f4331929d8d02A47b333Af1 93,559,311, 12:40:00
BNB Chain 0xFCD84210f5d51Cd40a30443d44d6A5500d5D10dF 0xAb6e2f343C1909258580e4E6A149E24CbB3D2AEd 121,071,830, 12:41:18
Arbitrum One 0xFC63B7C762B10670Eda15cF3ca3970bCDB28C9eF 0xD09302C533Ca020E02FF4F70BBa606e3C2b3F4a6 503,712,218, 12:42:47
Optimism 0xA3c8502187fD7a7118eAD59dc811281448946C8f 0x91b577553B5390d47A1984eE500663EE7671DcE6 156,722,738, 12:44:13
Avalanche C-Chain 0x3D9A67D5ec1E72CEcA8157e028855056786b6159 0xD226e7C591F6aE719079b8A31654221d980DB5ce 94,937,876, 12:45:01

What still has the old addresses

  • @superfluid-finance/metadata 1.6.5, the latest release (2026-10-01), as contractsV1.toga, and the dev branch of Superfluid's protocol-monorepo.
  • superfluid-sentinel. It takes the TOGA address from that package (its lockfile resolves 1.4.1, which has the same six addresses), and no setting overrides it.
  • The generated togaAddress map in @sfpro/sdk (superfluid-org/superfluid.pro), and the TOGA reference in superfluid-org/skills.

So a sentinel on these chains asks the old contract who the PIC is. If your PIC holds the seat on the new contract, the sentinel does not recognize it. It waits out the patrician window like any other closer, so it does not close inside your window, and unless someone else does, the reward goes to whoever closes first after the window. If your PIC holds a seat on the old contract, the sentinel closes inside the window and the reward goes to the new contract's seat. The sentinel also does not see NewPIC events on the new contract.

Check it yourself

In bash, with curl and jq. The script compares the metadata's toga with what the governance contract returns for getRewardAddress(host, address(0)):

curl -s https://cdn.jsdelivr.net/npm/@superfluid-finance/metadata/networks.json > networks.json

check() { # network-name rpc-url
  read -r gov host toga < <(jq -r --arg n "$1" '.[] | select(.name == $n) | .contractsV1 | "\(.governance) \(.host) \(.toga)"' networks.json)
  data="0x19df62ab$(printf '%064s' "${host#0x}" | tr ' A-F' '0a-f')$(printf '%064d' 0)"
  ra=$(curl -s -H 'content-type: application/json' "$2" \
    --data "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_call\",\"params\":[{\"to\":\"$gov\",\"data\":\"$data\"},\"latest\"]}" | jq -r .result)
  echo "$1  metadata: $toga  reward address: 0x${ra: -40}"
}

check xdai-mainnet     https://gnosis-rpc.publicnode.com
check polygon-mainnet  https://polygon-bor-rpc.publicnode.com
check optimism-mainnet https://optimism-rpc.publicnode.com
check arbitrum-one     https://arbitrum-one-rpc.publicnode.com
check avalanche-c      https://avalanche-c-chain-rpc.publicnode.com
check bsc-mainnet      https://bsc-rpc.publicnode.com
check base-mainnet     https://base-rpc.publicnode.com

On 2026-10-17 the two addresses differed on the first six lines and matched on Base.

What to change meanwhile

If you run a sentinel as PIC on one of the six chains:

  1. Bid on the new contract. Bidding works as before: an ERC-777 send of the bond to the TOGA address, with the exit rate abi-encoded as int96 in userData.
  2. Point the sentinel at it. In src/config/configuration.js, loadNetworkInfo, let an environment variable override the metadata:

diff - this.TOGA_CONTRACT = contractsV1.toga || undefined; + this.TOGA_CONTRACT = process.env.TOGA_CONTRACT || contractsV1.toga || undefined;

Then set TOGA_CONTRACT in .env to the new address for your chain. The sentinel loads .env itself, and the compose file passes it to the container. With the compose file, rebuild the image (docker compose up -d --build) so the change is in it. The other way is to edit contractsV1.toga for your chain in node_modules/@superfluid-finance/metadata/networks.json, which is the file the sentinel reads, but every yarn install or image build puts the old address back. 3. Check the startup log. Contracts: loaded toga contract at address: ... should show the new address. Once the sentinel sees your seat, it logs you are the active PIC now (not in observer mode). 4. Remove the override once a metadata release has the new addresses and your sentinel resolves that release.

If your own tooling reads TOGA state, ask the governance contract with getRewardAddress(host, token). It always returns the address that currently receives the rewards. Metadata can lag behind it, as it does now.