Skip to content

NAN 006: Owning Our Dependencies, a Nonce-Aware Mempool, and 24-Hour Votes ​

Posted by Unique on 2026-07-31. Releases: v2.16.0, v2.17.0. Prior mainnet upgrade: v2.15.0.

NAN 005 < Nibiru Advancement Notes (NANs) > NAN 007

NAN 006 cover

Summary ​

  • Our dependencies live in our repository. The Cosmos SDK, IBC Go, x/wasm, and the Wasm VM are first-party source under lib/ and x/wasm, so one PR can fix a bug that spans them.
  • One sender can't flood blocks with EVM transactions that can never execute. The mempool now tracks each sender's nonces.
  • Mainnet governance votes take 24 hours instead of 48.
  • Authz is off. No account can grant another account permission to act for it. Grants can't be created, executed, or revoked.
  • Chain maintenance can run every block without a bot. Wasm block hooks let a governed registry contract schedule privileged calls at the start and end of each block.
  • Events roll back with the EVM. A reverted EVM call takes its Cosmos events with it.
  • Balance queries understand both VMs. One query returns a token's Bank and ERC20 balances.

1) Why we stopped consuming forks ​

Nibiru had been running patched versions of the Cosmos SDK, wasmd, and the Wasm VM for a long time. Each lived in its own fork and repository. A fix that touched two layers, say the SDK and the EVM module, meant coordinated PRs across repositories, version bumps, and replace directives that drifted.

In July we moved all of it into the chain repository:

  • The Cosmos SDK and wasmd forks moved to lib/, with public module tags lib/cosmos-sdk/v0.47.14-nibiru and lib/wasmd/v0.44.1-nibiru so other Go projects can import them (PR #2646).
  • x/wasm became first-party chain code, and the Wasm VM's Go bindings moved to lib/wasmvm-ffi with their own CI and release tags (PR #2656).
  • IBC Go v7 moved to lib/ibc-go. We removed the ICS-29 fee middleware at the same time, since it was never active on mainnet (PR #2686).
  • The SDK and IBC Go were flattened into the root module, and protobuf generation now resolves them locally (PR #2690).

Moving Nibiru's dependencies in-tree

The cost was real. The flatten alone touched about 2,500 files, mostly import rewrites and regenerated protobuf code. The move also broke the version flags in release builds, which left nibid version empty until PR #2713 fixed it. CI now fails if a build has empty version fields, or if anything imports the upstream modules again.

Why one repository? Because these pieces were never really separate. The chain, the SDK fork, wasmd, and the Wasm VM change together. Keeping them in separate repositories hid that coupling instead of removing it. A patch in one place quietly changed a dependency somewhere else, and Go replace statements piled up to hold it all together. Google and Meta keep coupled code in one repository for the same reason, at far larger scale.

The payoff is that one PR can now fix a bug across the SDK, the EVM, and Wasm, and one test run covers all three. There are far fewer replace statements. Refactors and bug fixes are faster, and so is the loop from a change to a built binary to a passing end-to-end test. In October we did the same thing for the consensus engine.

2) A mempool that understands nonces ​

An EVM account's transactions run in nonce order. If nonce 11 is missing, nonce 12 can't run, however long it waits.

Before v2.17, a sender could submit a pile of transactions with future nonces. The node accepted anything within its future window and gossiped it to peers. Proposers could then pack blocks with transactions that had no chance of executing.

v2.17 adds an EVM-aware mempool (PR #2702):

  • It indexes transactions by sender and nonce.
  • Each sender gets at most 8 live nonce slots. A different transaction for a slot that's already taken is rejected.
  • Block proposals only include each sender's contiguous chain starting from the committed nonce. Gaps stay out.
  • After each block, recheck drops any transaction whose earlier nonces are missing.

A nonce-aware EVM mempool

Two choices are worth calling out. The PR first allowed 64 slots per sender, and we lowered it to 8 before release. We were dealing with heavy bursts of spam at the time, and real accounts rarely need many pending transactions. Most send two or three in a row, sometimes five, and we've almost never seen one need more than ten. A tight limit costs real users nothing and makes spamming the nodes harder. If usage grows into it, we can raise it.

The second choice is that there's no fee-based replacement. You can't resubmit the same nonce with a higher fee to jump ahead. That keeps the mempool simple, at the cost of a feature some wallets expect.

None of this needed a CometBFT fork or a consensus migration. The index is local to each node and only shapes which transactions get proposed. Block validation still requires exact nonces.

3) Faster governance ​

v2.16 cut mainnet's governance voting period from 48 hours to 24 (PR #2632). Even at two days, we kept waiting on votes for no reason. Validators reached quorum quickly, everyone was prepared for the upgrade, and the release sat until the window closed. Chains that ship a few times a year can afford week-long votes. Nibiru ships far more often than that, so we treat upgrades more like game patches than rare events. The one-day window has worked better for everyone.

4) Turning off authz ​

The Cosmos SDK's authz module lets one account grant another permission to send messages on its behalf. Every delegation path is one more way to act for an account, and we chose to close this one.

v2.16 disables it (PR #2629). MsgGrant, MsgExec, and MsgRevoke fail on every path, including through Wasm. The module stays registered so codecs and queries don't break. Existing grants stay in state, but none of them can be executed.

5) Smaller changes worth knowing ​

  • Wasm block hooks. A sudo-configured registry contract can plan privileged Wasm calls during BeginBlock and EndBlock, with bounded plans and isolated execution (PR #2667). Chain-level maintenance can now run on schedule without a bot sending transactions.
  • Events follow EVM snapshots. When the EVM reverts to a snapshot, the Cosmos events emitted after it go too (PR #2696). This finishes the work NAN 004 started.
  • ERC-2470 in genesis. New chains include the standard singleton factory for deterministic CREATE2 deployment (PR #2697).
  • Multi-VM balances. QueryBalance returns a token's Bank and ERC20 balances together, and reads WNIBI from its own ledger (PR #2630, PR #2631).

6) On Sai ​

  • Export your key. If you signed up with Google or another social login, you can now export your wallet's private key.
  • Volume fee tiers. The more you trade, the lower your fees.
  • Sai is readable by AI. llms.txt and an LLM sitemap describe Sai for agents and assistants.
  • A cleaner app. A compact order form, redesigned navigation, and portfolio cards on mobile.

References ​

Pull requests behind each section. The Sai repositories are private, so the text above describes each change on its own.

1) Why we stopped consuming forks

  • nibiru#2646: Public tags for the Cosmos SDK and wasmd forks.
  • nibiru#2656: Wasm VM build dependencies consolidated in the chain repo.
  • nibiru#2686: ibc-go in-tree.
  • nibiru#2690 and nibiru#2713: The vendored Cosmos SDK and IBC flattened into the repo, and a version fix after the flatten.

2) A mempool that understands nonces

3) Faster governance

4) Turning off authz

5) Smaller changes worth knowing

6) On Sai