Skip to content

Remove the tokenfactory module behind the v6.8 upgrade - #4536

Merged
alexander-sei merged 5 commits into
mainfrom
alex/remove-tokenfactory-module
Oct 15, 2026
Merged

alexander-sei merged 5 commits into
mainfrom
alex/remove-tokenfactory-module

Conversation

@alexander-sei

@alexander-sei alexander-sei commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Tokenfactory is still a fully live module on main. Anyone can create, mint, burn and re-admin factory/ denoms, CosmWasm contracts reach it through the create_denom, mint_tokens, burn_tokens, change_admin and set_metadata custom messages and the tokenfactory query route, and both bank keepers enforce its per-denom transfer allowlists. Only its unused governance route is gone so far (#4431). This removes the module outright behind the v6.8 upgrade, the same way #4319 removed oracle.

x/tokenfactory and proto/tokenfactory are deleted and the module is unwired from app.New. retiredtokenfactory.ModuleName joins v68DeletedStores, so the store loader deletes the tokenfactory store at the upgrade height and the handler drops its version-map entry. The handler also deletes the module's parameter subspace from the params store with pruneTokenfactoryParams (on v6.7 that is tokenfactory/allowlistmaxsize), so none of its state outlives it. The module account joins retiredModuleAccounts so its address stays blocked from receiving funds. The six Msg types move to a decode-only app/retiredtokenfactory package with the same type URLs and amino names, so historical blocks still decode for tx queries and debug_trace*. Their ValidateBasic returns ErrDeprecated (codespace tokenfactory, code 26, because codes 2 to 25 keep their historical meanings), so a new tokenfactory transaction is refused at CheckTx without paying a fee, and retiredtokenfactory_test.go pins their amino sign bytes against bytes captured from the removed module.

The factory/ transfer allowlist (IsInDenomAllowList and its setters) goes from both sei-cosmos/x/bank and giga/deps/xbank, and pruneDenomAllowLists deletes the stored entries in the v6.8 handler. Pacific-1 holds only two: a test denom restricted to its own creator and an empty list, so lifting the check changes nothing for a real token. The AllowList proto type stays in the sei-cosmos bank.proto because the retired MsgCreateDenom and MsgUpdateDenom reference it, while giga's unused generated copy of it is removed. Giga's embedded bank.proto descriptor is left as is: it registers under the same file name as the sei-cosmos one, so it has to keep describing AllowList whichever registration wins. Contracts that send tokenfactory messages or queries now get the existing "Unknown Sei Wasm Message" and "Unknown Sei Query Route" errors.

This is app-hash breaking at the v6.8 height, and unlike oracle there was no deprecation phase: from that height anything still creating, minting or burning factory/ denoms stops working, while existing balances stay in bank, remain transferable, and have a frozen supply. The part to scrutinise is evmrpc/tests/regression_test.go: two pacific-1 fixtures (0x29b9…, 0x534a…) executed a CosmWasm contract through the wasmd precompile that emitted tokenfactory messages, so they now trace as reverted with different gas, and they move the way #4230's pointer-creation fixtures did. A third fixture, 0xc2da…, calls the same contract but has traced as a revert since #4202, so its gas is unchanged and it now asserts the revert. More generally, tracing a pre-v6.8 block no longer reproduces mainnet where a tokenfactory transaction changed state that a later EVM transaction in the same block read, the limitation the oracle and vesting retirements already accepted. Fixtures that created tokenfactory denoms now use genesis uatom, the authz generic-grant test grants MsgSend instead, and the tokenfactory YAML suite, which CI never ran, is deleted. Validated with the v6.8-tagged and untagged app tests, the bank, giga, wasmbinding, evmrpc, x/, precompile, occ and testutil packages, golangci-lint, make fmtcheck, and make upgrade-test-offline from release/v6.7, whose fixture snapshots the params store so a v6.7-written database shows the parameter prune touches nothing else; the cross-version and docker-cluster suites have not run yet.

alexander-sei and others added 2 commits October 13, 2026 10:58
Delete x/tokenfactory and proto/tokenfactory, unwire the module from the app,
and delete the tokenfactory store and version-map entry at the v6.8 upgrade.
The six Msg types move to a decode-only app/retiredtokenfactory package so
historical transactions still decode; new ones are refused at CheckTx.

Remove the factory/ denom transfer allowlist from the sei-cosmos and giga bank
keepers and prune the stored allowlists at v6.8. Drop the tokenfactory wasm
custom messages and query route, the tooling entries, and the tests and CI
fixtures that created tokenfactory denoms.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedOct 15, 2026, 11:04 AM

@codecov

codecov Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.27273% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.39%. Comparing base (83762fa) to head (e964473).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
wasmbinding/queries.go 0.00% 3 Missing ⚠️
sei-cosmos/x/bank/keeper/msg_server.go 0.00% 2 Missing ⚠️
app/app.go 0.00% 1 Missing ⚠️
wasmbinding/wasm.go 0.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4536      +/-   ##
==========================================
+ Coverage   57.29%   57.39%   +0.10%     
==========================================
  Files        2143     2125      -18     
  Lines      167425   166618     -807     
==========================================
- Hits        95927    95636     -291     
+ Misses      71493    70977     -516     
  Partials        5        5              
Flag Coverage Δ
sei-chain 55.46% <87.27%> (+<0.01%) ⬆️
sei-db 75.17% <ø> (ø)
sei-db-state-db 80.07% <ø> (+1.00%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
app/apptesting/test_suite.go 0.00% <ø> (ø)
app/encoding.go 100.00% <100.00%> (ø)
app/retiredtokenfactory/codec.go 100.00% <100.00%> (ø)
app/retiredtokenfactory/msgs.go 100.00% <100.00%> (ø)
app/upgrades.go 45.68% <100.00%> (+1.93%) ⬆️
giga/deps/xbank/keeper/send.go 87.19% <ø> (-1.89%) ⬇️
giga/deps/xbank/types/key.go 32.00% <ø> (+2.37%) ⬆️
loadtest/loadtest_client.go 0.00% <ø> (ø)
loadtest/main.go 0.00% <ø> (ø)
loadtest/types.go 0.00% <ø> (ø)
... and 10 more

... and 44 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@alexander-sei

Copy link
Copy Markdown
Contributor Author

@seidroid review

@seidroid seidroid Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This removes the tokenfactory module behind the v6.8 upgrade. The store is deleted and its version-map entry dropped, the six Msg types stay decodable but are refused at validation (codespace tokenfactory, code 26), and the factory/ transfer allowlist is dropped from both bank keepers and pruned from the bank store in the handler. I found nothing blocking: the 0x11 prefix holds only allowlist keys, so the prune touches nothing else in the bank store; sign bytes, type URLs and fee-free refusal are covered by tests; and the one scout claim (codex, about the v6.0.2/v6.0.3 regression fixtures) was dropped because REVIEW.md §2 rules out a newer binary re-executing or tracing pre-upgrade heights, so the fixture shift is the accepted limitation the description names.

Non-blocking

  • The pacific-1 regression fixtures changed here (0x29b9…, 0x534a…, and the unchanged 0xc2da…) show a CosmWasm contract minting factory/sei1e3gttzq5…/isei through tokenfactory custom messages. If that contract is still live, its mint and burn flows will start reverting at the v6.8 height with no deprecation window, and the supply it backs will be frozen. Confirm its operators know before the upgrade is proposed.

seidroid review · decision approve · session 265dd04dce2a4eb8ae9eb29efa074f6c · turn resp_claude_e0cea4438970e083040428afdf1aaea5 · item 26e262db61d45a149c7564fac9fa8104

Findings: 0 blocking | 1 non-blocking | 0 posted inline

The v6.8 handler now also deletes the tokenfactory parameter subspace from
the params store, so none of the module's state outlives it. The in-process
test seeds the parameter v6.7 keeps and a creation fee an older version left
behind, and the offline fixture adds the params store to its retained-store
snapshot, so a v6.7-written database shows the prune touches nothing else.

Drop the unused AllowList copy from giga's bank.pb.go. Its embedded
descriptor is left as is: it registers under the same file name as the
sei-cosmos descriptor, which still has to describe AllowList for the retired
tokenfactory messages. Also correct the AllowList field comment, delete the
factoryDenomPrefix constants only the removed allowlist tests used, and mark
the 0xc2da regression fixture as a revert, which it has traced as since
#4202.

Co-authored-by: Cursor <cursoragent@cursor.com>
@alexander-sei
alexander-sei marked this pull request as ready for review October 13, 2026 23:25
@cursor

cursor Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

PR Summary

High Risk
State-machine-breaking upgrade that deletes a module store, changes bank transfer rules for factory denoms, and alters historical EVM trace semantics for wasm/tokenfactory paths.

Overview
Removes the tokenfactory module as part of the v6.8 upgrade (same pattern as oracle retirement): x/tokenfactory and its protos, CLI, store, wasm plugins, and bank factory/ transfer allowlist enforcement are deleted from the live app. The upgrade drops the tokenfactory KV store, clears module version-map entries, prunes tokenfactory params from the params store, and deletes up to 1,000 denom allowlist keys per prefix (any remainder stay in state but are no longer enforced).

Decode-only compatibility lives in app/retiredtokenfactory: historical Msg types keep their type URLs and amino identity but ValidateBasic returns ErrDeprecated, so new tokenfactory txs fail at CheckTx without fees. Existing factory/ bank balances remain spendable; allowlist-restricted denoms become freely transferable after pruning.

Bank / Giga no longer implement SetDenomAllowList, GetDenomAllowList, or IsInDenomAllowList on sends. Integration tests, loadtest, and contract helpers stop creating tokenfactory denoms (fixtures use genesis uatom / bank metadata instead). EVM RPC regression expectations change for traces that executed wasm emitting tokenfactory messages.

App-hash breaking at the v6.8 upgrade height.

Reviewed by Cursor Bugbot for commit e964473. Bugbot is set up for automated code reviews on this repo. Configure here.

Creating a tokenfactory denom allowlist costs only gas, and each one is a
single bank key, even when the list is empty. The v6.8 handler deleted all
of them in the upgrade block, so anyone could grow that work before the
upgrade height. The delete held every key in memory and left every delete
pending in the bank cache for the rest of the block, where each bank
iterator a transaction opened had to scan them.

deleteByPrefix, which every v6.8 prune goes through, now deletes at most
RetiredPrefixDeleteLimit (1,000) keys in key order and leaves the rest.
Nothing reads the allowlists after this change, so any that survive are
inert. DenomAllowListPrefix is declared again in both bank key.go files,
marked deprecated, so no later bank key reuses 0x11, and the app's private
copy of the prefix is gone.

TestV68DenomAllowListPruneIsBounded seeds one allowlist more than the limit
and checks that only the last one survives and that it does not restrict a
send of its denom. The CHANGELOG entry now says that denoms with an
allowlist become freely transferable.

At pacific-1 height 237,714,318 there are two allowlists and atlantic-2 has
36, so both networks still end up with none.

Co-authored-by: Cursor <cursoragent@cursor.com>
@alexander-sei

Copy link
Copy Markdown
Contributor Author

@sei-will I've addressed both points from your Slack comments in e964473.

On the unbounded work in the upgrade block: deleteByPrefix, which every v6.8 prune goes through, now deletes at most RetiredPrefixDeleteLimit (1,000) keys under a prefix, in key order, and leaves the rest. That keeps pruneDenomAllowLists bounded however many allowlists get created before the upgrade height, since each one costs only gas and is a single bank key, even when the list is empty. Allowlists past the cap are inert because nothing reads 0x11 after this PR, and DenomAllowListPrefix stays declared as deprecated in both bank key.go files so the prefix can't be reused. TestV68DenomAllowListPruneIsBounded seeds 1,001 allowlists and checks that only the last one survives and that it doesn't restrict a send. The other v6.8 deletes don't have this problem: dropping the tokenfactory store removes its memIAVL tree in one step regardless of size, and the params and upgraded IBC state prunes only touch a few keys that governance wrote.

On restricted denoms becoming freely transferable: that's intended, and the CHANGELOG entry now says so plainly. For the record, at pacific-1 height 237,714,318 there are two allowlists:

  • factory/sei1dg8unurclh6p05tu64nsth5642mm6gx5nt86hk/test-1, one address, supply 100,000,000
  • factory/sei1eyptzng905pfaavl3seunu5p84heur0e07k3pm/ALLOW, empty, so it restricts nothing

atlantic-2 has 36, all on test denoms. TestV68SendsADenomItsAllowListRestricted pins that after v6.8 a denom its allowlist restricted can be sent to an address the list didn't name.

@alexander-sei
alexander-sei added this pull request to the merge queue Oct 15, 2026
Merged via the queue into main with commit 8d901ea Oct 15, 2026
61 checks passed
@alexander-sei
alexander-sei deleted the alex/remove-tokenfactory-module branch October 15, 2026 12:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants