Skip to content

fix: Account Balances page#6793

Merged
filippoweb3 merged 12 commits intow3f:masterfrom
Imod7:domi-update-account-balances
Jul 28, 2025
Merged

fix: Account Balances page#6793
filippoweb3 merged 12 commits intow3f:masterfrom
Imod7:domi-update-account-balances

Conversation

@Imod7
Copy link
Copy Markdown

@Imod7 Imod7 commented Jul 23, 2025

Description

Related to this issue #6787

Review

Review from @Ank4n would be very helpful! Thank you very much in advance!

governance etc. but is not necessarily spendable (or transferrable)
- **Frozen** is the free balance locked for [staking](./learn-staking.md),
[governance](./learn-polkadot-opengov.md), and [vesting](./learn-transactions.md#vested-transfers)
- **Free** is the balance that can be used for on-chain activity like participating in
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 is complex to explain, but here is how I would explain it. I would still like to get more eyes on this to verify @filippoweb3 @DrW3RK

  • Free Balance: Balance that can be used for any on-chain activity (staking, governance, deposits) as long as your total balance (free + reserved) remains above the maximum of frozen balance and existential deposit.

  • Frozen Balance (also called locks): This is a balance that overlaps across pallets . Example: If governance freezes 100 DOT and vesting freezes 120 DOT, total frozen = 120 DOT (not 220 DOT).

  • Reserved Balance (also called holds): Balance removed from free and doesn't overlap. Used by Nomination Pools, Staking, etc. Can still be used for governance voting but not for transfers or fees.

  • Spendable Balance: Portion of free balance available for transaction fees and creating new holds.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I am on it, I need to verify a couple of things but there is already PR in place to update the balances page.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@filippoweb3 Let me know if you would like to incorporate the changes reviewed by Ankan into your PR, and I can close mine. Otherwise, I am happy to add them to this PR.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Just pushed the changes suggested from @Ank4n in this commit

@@ -12,16 +12,10 @@ remain frozen and unused due to an on-chain requirement.

There are 5 types of account balances:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

4

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Updated in this commit

- **Reserved** (also called holds) is the balance removed from free and doesn't overlap. Used by nomination pools, [staking](./learn-staking.md), etc. Can still be used for governance voting but not for transfers or fees.
- **Spendable** is the portion of free balance available for transaction fees and creating new holds.

The spendable balance is calculated as follows:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This needs to be updated as part of this PR. E.g. on_hold is no longer defined. Does the formula need an update? @Ank4n

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I updated the formula in this commit. If there are any objections from Ankan I will edit again.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this is sadly not correct, since a reserved balance creates a provider ref which makes the ED spendable. I will check again how it is exactly, but more complicated than the formula currently.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

IMO it should be something like this. It is also not 100% correct though, see the NOTE. So not sure how to easily explain this. In practice its not easy.

untouchable = frozen - on_hold.min(frozen);

// NOTE: The `(on_hold > 0 || frozen > 0)` is an *approximation* for
// `(consumers != 0 && providers <= 1)`, which is the condition that actually matters.
if free > 0 && (on_hold > 0 || frozen > 0) {
	untouchable = untouchable.max(ed);
}

spendable = free - untouchable.min(free);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

We have a test case here demonstrating that when a hold exists, the ED is not spendable.

Here’s the AccountInfo for 11 from that test (not printed in the test output, but retrieved by running it locally):

AccountInfo {
    nonce: 0,
    consumers: 1,
    providers: 1,
    sufficients: 0,
    data: AccountData {
        free: 1,
        reserved: 1000,
        frozen: 0,
        flags: ...
    }
}

Copy link
Copy Markdown
Collaborator

@joepetrowski joepetrowski left a comment

Choose a reason for hiding this comment

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

There are still changes below (spendable calculation, examples) that need to be made.

@Imod7
Copy link
Copy Markdown
Author

Imod7 commented Jul 24, 2025

There are still changes below (spendable calculation, examples) that need to be made.

  • I updated the examples but the changes need to be double checked.
  • Once the example changes are confirmed, the photos will need to be aligned. I am not sure what tool to use to edit them, but I assume @filippoweb3 will know how to handle this.
  • Also, this section Query Account Data in Polkadot-JS was updated.
  • Untouchable should either be added again in the balance types or be removed from the examples to maintain consistency.

@filippoweb3
Copy link
Copy Markdown
Contributor

filippoweb3 commented Jul 24, 2025

@Imod7 I will have a look by EoW, will update the figures as well. I will push my edits, ask for review by @michalisFr and merge. Thank you so much for starting this PR!

- new figures + description
- updated text
Frozen (locked): 50 DOT
Reserved (held): 80 DOT
Spendable: 19 DOT (Free - ED)
Untouchable: 51 DOT (ED)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A vested transfer increases the total balance as well. At the end of the day when all locks and reserves are removed you should have 150 DOT transferable. Also, in this example you suddenly have more frozen than free, so you lose access to the 20 DOT you had before.

What would happen here is this:
Free: 70
Frozen: 50
Reserved: 80
Spendable: 69
Untouchable: 1

However, since Frozen overlaps with Reserved, as you can see you have that 50 extra DOT as spendable from day 1. But at the end of the day that's not a problem since if you remove all reserves and the governance lock, you'll still have 50 DOT frozen that will become spendable according to the vesting schedule.

But again I'd like @joepetrowski or @Ank4n to confirm.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

added an example for a second gov lock as vesting can be a further example.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I did not read through the context here, but i had this in my notes. Will compare against it:

|__total__________________________________|
|__on_hold__|_____________free____________|
|__________frozen___________|
|__on_hold__|__ed__|        
            |__untouchable__|__spendable__|

untouchable = max(ed, frozen - on_hold)

from here.

Copy link
Copy Markdown

@Ank4n Ank4n left a comment

Choose a reason for hiding this comment

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

I added a few suggestions, but overall, great job.


- **Free Balance** is a portion of an account's total balance that is not held (see below). It is the balance that can be used for any on-chain activity ([staking](./learn-staking.md), [governance](./learn-polkadot-opengov.md), and deposits) as long as the total balance (free + reserved) remains above the maximum of frozen balance and existential deposit.

- **Reserved Balance** (also called holds, or held balance) is the balance removed from free and does not overlay. It can be slashed, but only after all the free balance has been slashed. Reserved balance is used for:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

...but only after all the free balance has been slashed

Not sure what this means - shouldn’t only the reserved funds be subject to slashing? Why would the free balance be slashed?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for pointing out. This is not correct anymore. I think the original text was correct when staking was using locks, and it was part of free balance.

(I will make a fix in the fungible rustdoc)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

(pending review) fix

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@filippoweb3 This text should be fixed too. Totally misleading as it is now. You can refer the text here.

On hold: 0 DOT
Frozen (locked): 0 DOT
Reserved (held): 0 DOT
Spendable: 99 DOT
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

A subtle nuance to explain is that the spendable balance is 99 DOT if you intend to keep the account alive. However, if you’re fine with the account being reaped, you can transfer up to the full 100 DOT (minus transaction fees).

@Ank4n
Copy link
Copy Markdown

Ank4n commented Jul 28, 2025

I had a question today about voting locks, and it wasn’t clear to the person asking — and probably not to many others either — that governance votes use the total balance, including non-staking holds (like proxy deposits).

Might be worth calling this out explicitly in the docs as well:
https://github.com/paritytech/polkadot-sdk/blob/master/substrate/frame/conviction-voting/src/lib.rs#L425

Also, I think we should go ahead and merge this (post handing current open comments). It’s not perfect, but already a clear improvement over what’s currently in the docs. We can continue to iterate on it from here.
Approving this PR for that reason.

Filippo added 2 commits July 28, 2025 13:07
- consumer and provider refs
- Oliver's feedback
- minor last edits
@filippoweb3 filippoweb3 merged commit b27407a into w3f:master Jul 28, 2025
5 checks passed
@filippoweb3 filippoweb3 mentioned this pull request Jul 28, 2025
@Ank4n
Copy link
Copy Markdown

Ank4n commented Jul 29, 2025

@filippoweb3 Regarding the balance examples, how are they currently being cross-verified? Should we add dedicated unit tests in the SDK to match each example one-to-one? Or any other idea?

@filippoweb3
Copy link
Copy Markdown
Contributor

@Ank4n we validate with Polkadot JS and the support team :) I would wait to build unit tests until those figures and examples are final, as the Wiki content is subject to changes, and this would add additional work to update test dependencies. Thanks!

github-merge-queue bot pushed a commit to paritytech/polkadot-sdk that referenced this pull request Jul 30, 2025
## Changes
- Updated the `Held Balance` definition to reflect the current behavior.
The previous explanation was accurate when staking used locks (which
were part of the free balance), but since [staking now uses
holds](#5501), the old
definition is misleading.
This issue was originally pointed out by @michalisFr
[here](w3f/polkadot-wiki#6793 (comment)).
- Fixed a broken reference in the deprecated doc for `ExposureOf`, which
was (ironically) pointing to a non-existent type named `ExistenceOf`.
This slipped in during our [mega async staking
PR](#8127).
alvicsam pushed a commit to paritytech/polkadot-sdk that referenced this pull request Oct 17, 2025
## Changes
- Updated the `Held Balance` definition to reflect the current behavior.
The previous explanation was accurate when staking used locks (which
were part of the free balance), but since [staking now uses
holds](#5501), the old
definition is misleading.
This issue was originally pointed out by @michalisFr
[here](w3f/polkadot-wiki#6793 (comment)).
- Fixed a broken reference in the deprecated doc for `ExposureOf`, which
was (ironically) pointing to a non-existent type named `ExistenceOf`.
This slipped in during our [mega async staking
PR](#8127).
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.

6 participants