TL;DR
Building DApps on Polkadot can result in suboptimal UX due to the lack of atomic multi-call flows where later actions depend on the state changes from earlier ones. Could pallet-revive
(or more generally, smart contracts with access to runtime pallets) help solve this?
The Problem: Chained Transactions Kill UX
One of the biggest pain points when developing DApps on Polkadot is the inability to perform certain actions atomically. Often, we have to:
- Submit a transaction.
- Wait for its block-inclusion (and sometimes finalization).
- Extract some state from it (or read some events).
- Submit a second transaction.
This flow introduces friction and complexity that significantly harms user experience.
A Real Example: KSM RFP #2 RFP-launcher Dapp
While building the RFP-launcher, we needed to do the following in one go:
- Create a bounty.
- Submit a referendum for that bounty.
- Plus a few other related calls.
Ideally, all of this would happen in one transaction. But here’s what we ran into:
Option 1: Guessing the Bounty ID
Since bounty IDs are incrementally assigned, we could try to guess the next ID and use it in the same batch. Most of the time this works — but if someone else creates a bounty just before our transaction is included, everything breaks: we end up referencing the wrong bounty in the referendum.
Technically, we could detect this in the DApp and guide the user through a recovery flow. But that’s still a terrible experience.
Option 2: Sequential Transactions
Instead, we create the bounty in one transaction, wait for it to be included, extract the ID from the emitted event, and then send a second transaction with the rest of the operations. Safer, but introduces delay, complexity, and additional signing — not great UX either.
This Isn’t Just About Bounties…
This pattern pops up all over Polkadot: you want to conditionally chain actions where subsequent calls depend on freshly-updated state. Current options are either unsafe or clunky.
Can pallet-revive
solve this?
If smart contracts deployed through pallet-revive
could tap into other pallets functionalities, we could deploy a contract that:
- Creates the bounty.
- Grabs the real ID immediately.
- Submits the referendum referencing the correct bounty — all in one atomic call.
This would open up far more powerful transaction flows than what’s currently feasible today.
Is This Possible Today?
I might be wrong here, but my assumption is this isn’t currently viable due to how contracts and pallets differ:
- FRAME pallets: Use weight-based fees estimation (run on WASM).
- Contracts (e.g., Ink! via revive): Use gas-based metering (run on PVM).
This separation likely prevents contracts from invoking pallet logic directly. I could be wrong, though… I really wish to be wrong! But — if Ink! (on pallet-revive) offered a safe interface to tap into other pallets, it could be a game-changer.
Is Anyone Exploring This?
Is there ongoing work in this direction? Could a smart contract system bridge this gap to allow conditional flows without race conditions or multi-transaction UX hurdles?
Would love to hear if someone is exploring this or if there are design discussions happening around it.
cc: @Alex @alejandro @peterw
PS: Yes, I’m aware that in the bounty case we could theoretically refactor things — e.g., by making the bounty ID deterministic (like, being a hash of the bounty info). But that’s a major refactor and doesn’t generalize well. The core issue remains: we need a clean way to express “do X, then Y based on X’s result” without breaking the UX.