Skip to content

Recycle fees via chain ext with immutable custodial fallback#48

Draft
LandynDev wants to merge 3 commits intomainfrom
feat/recycle-fallback
Draft

Recycle fees via chain ext with immutable custodial fallback#48
LandynDev wants to merge 3 commits intomainfrom
feat/recycle-fallback

Conversation

@LandynDev
Copy link
Copy Markdown
Collaborator

@LandynDev LandynDev commented Apr 15, 2026

Alternative to #9

Same chain-ext call, plus an immutable custodial fallback so a signature mismatch
or slipped subtensor rollout can't trap fees in the contract.

How it works

  • recycle_fees is permissionless
  • Every call tries add_stake_recycle first (the chain extension, that doesn't exist today)
  • The First success of this chain ext will flip chain_ext_enabled = true. Permanently after that, chain ext is the only path of recycling.
  • Until the flip, a failed chain-ext call falls back to: env.transfer(recycle_address, fees) -> custodial wallet transfer
  • recycle_address is set in the constructor — no setter, nobody can change it
  • Emits ChainExtensionLatched once when the flip happens
  • Emits FeesRecycled { via_chain_ext } on every recycle

Why implement it like this?

The subtensor chain extension is still weeks out, probably 30th at earliest before it hits mainnet.

We don't want to sit on our hands waiting for it to ship. This lets us deploy now with the custodial wallet actually wired up, and the moment the chain extension lands on mainnet, the first recycle_fees call after that flips us over to it automatically and permanently.

No contract upgrade, redeploy, or admin action.

By rolling something like this out early, we'd still be pinned to the requirement

function_id = 18
add_stake_recycle(hotkey, netuid, amount)

If for some reason the mainnet deployment differs from these mappings then a redeployment of the contract would be necessary since its non upgradeable. This is worth a check/ask with subtensor team maybe

Follow-ups (not in this draft)

  • Constructor takes recycle_address again — CLI deploy + admin need updating
  • Regenerate metadata/allways_swap_manager.json

recycle_fees() now calls the subtensor AddStakeRecycleV1 chain
extension (func_id 18) to atomically stake and recycle fees on-chain
instead of transferring TAO to an external wallet.

Adds SubtensorExtension trait with CustomEnvironment for ink! chain
extension support. Requires subtensor chain extension func_ids 16-19.
Chain extension handles fee recycling on-chain now, so recycle_address
storage, setter, getter, and CLI command are dead code. Also adds
pre-check for zero fees and a hint when ContractReverted occurs.
Probe-and-latch: recycle_fees tries the chain extension on every call. On
success it permanently latches chain_ext_enabled=true and stops falling
back. Until then, a chain-ext failure transfers fees to the immutable
recycle_address set at construction (no setter, no owner override). Once
latched, the custodial path is dead forever.

Also makes recycle_fees permissionless — anyone can trigger it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant