Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Contracts: seal0::balance should return the free balance #1254

Merged
merged 6 commits into from
Sep 1, 2023

Conversation

xermicus
Copy link
Member

In seal0, the balance API function is supposed to return the "free" balance. I noticed that this was indeed the case with substrate contracts node < v0.25.0. However, with current versions, the free balance + the ED is returned instead. I don't think this is the wanted behavior, and if it was I think it'd constitute a breaking change requiring a new version for balance.

…ance

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
@xermicus xermicus added R0-silent Changes should not be mentioned in any release notes T7-smart_contracts This PR/Issue is related to smart contracts. labels Aug 29, 2023
@paritytech-ci paritytech-ci requested review from a team August 29, 2023 12:05
@@ -1367,7 +1367,11 @@ where
}

fn balance(&self) -> BalanceOf<T> {
Copy link
Contributor

@pgherveou pgherveou Aug 29, 2023

Choose a reason for hiding this comment

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

good catch, looks like this is a regression from paritytech/substrate#14020

 	fn balance(&self) -> BalanceOf<T> {
-		T::Currency::free_balance(&self.top_frame().account_id)
+		T::Currency::balance(&self.top_frame().account_id)
 	}

Copy link
Member

Choose a reason for hiding this comment

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

Those are different traits. On the Currency trait (before) we had free_balance. But on the new trait Inspect it is just balance which also doesn't include holds or freezes.

substrate/frame/contracts/src/tests.rs Outdated Show resolved Hide resolved
Comment on lines +53 to +59
;; Make the transferred value exceed the balance by adding the minimum balance.
(i64.store (i32.const 0)
(i64.add
(i64.load (i32.const 0))
(i64.load (i32.const 16))
)
)
Copy link
Contributor

Choose a reason for hiding this comment

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

isn't it simpler not to modify the fixture but to add ED to the transferred balance?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, not sure what you mean, this does add the ED to the transferred balance. How would I do that without modifying the fixture?

Copy link
Member Author

@xermicus xermicus Aug 29, 2023

Choose a reason for hiding this comment

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

I mean the fixture is broken, given seal_balance should only return free balance: It tries to send away all free balance but expects the transfer to fail. Which should never fail. Hence we need to modify it anyways.

Co-authored-by: PG Herveou <pgherveou@gmail.com>
Copy link
Contributor

@juangirini juangirini left a comment

Choose a reason for hiding this comment

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

The definition of balance used in substrate contracts node < v0.25.0 was this

	fn balance(&self) -> BalanceOf<T> {
		T::Currency::free_balance(&self.top_frame().account_id)
	}

https://github.com/paritytech/substrate/blob/6fa7fe1326ecaab9921c2c3888530ad679cfbb87/frame/contracts/src/exec.rs#L1290-L1292

This was the free_balance definition:

	/// The 'free' balance of a given account.
	///
	/// This is the only balance that matters in terms of most operations on tokens. It alone
	/// is used to determine the balance when in the contract execution environment. When this
	/// balance falls below the value of `ExistentialDeposit`, then the 'current account' is
	/// deleted: specifically `FreeBalance`.
	///
	/// `system::AccountNonce` is also deleted if `ReservedBalance` is also zero (it also gets
	/// collapsed to zero if it ever becomes less than `ExistentialDeposit`.
	fn free_balance(who: &AccountId) -> Self::Balance;

https://github.com/paritytech/substrate/blob/6fa7fe1326ecaab9921c2c3888530ad679cfbb87/frame/support/src/traits/tokens/currency.rs#L101-L110
This implies that free_balance sums up the ed.

In fact its implementation is just to return the free balance

	fn free_balance(who: &T::AccountId) -> Self::Balance {
		Self::account(who).free
	}

https://github.com/paritytech/substrate/blob/6fa7fe1326ecaab9921c2c3888530ad679cfbb87/frame/balances/src/lib.rs#L1479-L1481

Which does never mention to not include ed

	/// Non-reserved part of the balance. There may still be restrictions on this, but it is the
	/// total pool what may in principle be transferred, reserved and used for tipping.
	///
	/// This is the only balance that matters in terms of most operations on tokens. It
	/// alone is used to determine the balance when in the contract execution environment.
	pub free: Balance,

https://github.com/paritytech/substrate/blob/6fa7fe1326ecaab9921c2c3888530ad679cfbb87/frame/balances/src/lib.rs#L691-L712

How is possible that the ed was not summed up in the 'old' balance calculation?

@xermicus
Copy link
Member Author

You are right, that comment you found is confusing.

[... ] When this
/// balance falls below the value of ExistentialDeposit

Implies that ED would be included in "free" balance. However, that doesn't make sense to me based just the notions of "free" balance and "existential deposit": How can "free" balance include something called "existential deposit", which destroys your account if sent away? Which is not exactly what I'd understand of "free" balance. I think that might just have been a documentation issue?

@juangirini
Copy link
Contributor

I don't think it's a documentation issue

/// Force the new free balance of a target account `who` to some new value `balance`.
fn make_free_balance_be(
who: &T::AccountId,
value: Self::Balance,
) -> SignedImbalance<Self::Balance, Self::PositiveImbalance> {
Self::try_mutate_account_handling_dust(
who,
|account,
is_new|
-> Result<SignedImbalance<Self::Balance, Self::PositiveImbalance>, DispatchError> {
let ed = T::ExistentialDeposit::get();
// If we're attempting to set an existing account to less than ED, then
// bypass the entire operation. It's a no-op if you follow it through, but
// since this is an instance where we might account for a negative imbalance
// (in the dust cleaner of set_account) before we account for its actual
// equal and opposite cause (returned as an Imbalance), then in the
// instance that there's no other accounts on the system at all, we might
// underflow the issuance and our arithmetic will be off.
ensure!(value >= ed || !is_new, Error::<T, I>::ExistentialDeposit);
let imbalance = if account.free <= value {
SignedImbalance::Positive(PositiveImbalance::new(value - account.free))
} else {
SignedImbalance::Negative(NegativeImbalance::new(account.free - value))
};
account.free = value;
Self::deposit_event(Event::BalanceSet { who: who.clone(), free: account.free });
Ok(imbalance)
},
)
.unwrap_or_else(|_| SignedImbalance::Positive(Self::PositiveImbalance::zero()))
}
}

Copy link
Member

@athei athei left a comment

Choose a reason for hiding this comment

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

The regression was not in paritytech/substrate#14020 as @juangirini pointed out. It happened when we had to adapt to the fact that reserved balance can no longer contribute to the ed.

We always included the ed in the free balance. However, before the ed was part of reserved balance and you could send away everything returned by balance. And we should go back to this behaviour. Good catch.

@xermicus
Copy link
Member Author

xermicus commented Sep 1, 2023

bot fmt

@command-bot
Copy link

command-bot bot commented Sep 1, 2023

@xermicus https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/3526923 was started for your command "$PIPELINE_SCRIPTS_DIR/commands/fmt/fmt.sh". Check out https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/pipelines?page=1&scope=all&username=group_605_bot to know what else is being executed currently.

Comment bot cancel 10-4bf6d9ac-8685-43b7-b819-986e4350e5f2 to cancel this command or bot cancel to cancel all commands in this pull request.

@command-bot
Copy link

command-bot bot commented Sep 1, 2023

@xermicus Command "$PIPELINE_SCRIPTS_DIR/commands/fmt/fmt.sh" has finished. Result: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/3526923 has finished. If any artifacts were generated, you can download them from https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/3526923/artifacts/download.

@xermicus
Copy link
Member Author

xermicus commented Sep 1, 2023

Ah now I see. Thanks @athei

@xermicus
Copy link
Member Author

xermicus commented Sep 1, 2023

bot merge

@command-bot
Copy link

command-bot bot commented Sep 1, 2023

@xermicus Unknown command "merge". Refer to help docs and/or source code.

@xermicus xermicus enabled auto-merge (squash) September 1, 2023 11:46
@xermicus xermicus merged commit 24c41f1 into master Sep 1, 2023
106 of 107 checks passed
@xermicus xermicus deleted the cl/contracts-balance-api-version-0 branch September 1, 2023 12:33
ordian added a commit that referenced this pull request Sep 1, 2023
* master: (25 commits)
  fix typos (#1339)
  Use bandersnatch-vrfs with locked dependencies ref (#1342)
  Bump bs58 from 0.4.0 to 0.5.0 (#1293)
  Contracts: `seal0::balance` should return the free balance (#1254)
  Logs: add extra debug log for negative rep changes (#1205)
  Added short-benchmarks for cumulus (#1183)
  [xcm-emulator] Improve hygiene and clean up (#1301)
  Bump the known_good_semver group with 1 update (#1347)
  Renames API (#1186)
  Rename `polkadot-parachain` to `polkadot-parachain-primitives` (#1334)
  Add README to project root (#1253)
  Add environmental variable to track decoded instructions (#1320)
  Fix polkadot-node-core-pvf-prepare-worker build with jemalloc (#1315)
  Sassafras primitives (#1249)
  Restructure `dispatch` macro related exports (#1162)
  backing: move the min votes threshold to the runtime (#1200)
  Bump zstd from 0.11.2+zstd.1.5.2 to 0.12.4 (#1326)
  Remove `substrate_test_utils::test` (#1321)
  remove disable-runtime-api (#1328)
  [ci] add more jobs for pipeline cancel, cleanup (#1314)
  ...
ordian added a commit that referenced this pull request Sep 7, 2023
* master: (25 commits)
  Markdown linter (#1309)
  Update `fmt` file and some authors (#1379)
  Bump the known_good_semver group with 1 update (#1375)
  Bump proc-macro-warning from 0.4.1 to 0.4.2 (#1376)
  feat: add futures api to `TransactionPool` (#1348)
  Ensure cumulus/bridges is ignored by formatter and run it (#1369)
  substrate: chain-spec paths corrected in zombienet tests (#1362)
  contracts: Update to wasmi 0.31 (#1350)
  [improve docs]: Template pallet (#1280)
  [xcm-emulator] Unignore cumulus integration tests (#1247)
  Fix wrong ref counting (#1358)
  Use cached session index to obtain executor params (#1190)
  fix typos (#1339)
  Use bandersnatch-vrfs with locked dependencies ref (#1342)
  Bump bs58 from 0.4.0 to 0.5.0 (#1293)
  Contracts: `seal0::balance` should return the free balance (#1254)
  Logs: add extra debug log for negative rep changes (#1205)
  Added short-benchmarks for cumulus (#1183)
  [xcm-emulator] Improve hygiene and clean up (#1301)
  Bump the known_good_semver group with 1 update (#1347)
  ...
bgallois pushed a commit to duniter/duniter-polkadot-sdk that referenced this pull request Mar 25, 2024
serban300 pushed a commit to serban300/polkadot-sdk that referenced this pull request Apr 8, 2024
serban300 pushed a commit to serban300/polkadot-sdk that referenced this pull request Apr 8, 2024
serban300 pushed a commit to serban300/polkadot-sdk that referenced this pull request Apr 8, 2024
serban300 pushed a commit to serban300/polkadot-sdk that referenced this pull request Apr 8, 2024
serban300 pushed a commit to serban300/polkadot-sdk that referenced this pull request Apr 9, 2024
serban300 pushed a commit to serban300/polkadot-sdk that referenced this pull request Apr 9, 2024
serban300 pushed a commit to serban300/polkadot-sdk that referenced this pull request Apr 9, 2024
serban300 pushed a commit to serban300/polkadot-sdk that referenced this pull request Apr 9, 2024
serban300 pushed a commit to serban300/polkadot-sdk that referenced this pull request Apr 9, 2024
serban300 pushed a commit to serban300/polkadot-sdk that referenced this pull request Apr 9, 2024
serban300 pushed a commit to serban300/polkadot-sdk that referenced this pull request Apr 10, 2024
serban300 pushed a commit to serban300/polkadot-sdk that referenced this pull request Apr 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
R0-silent Changes should not be mentioned in any release notes T7-smart_contracts This PR/Issue is related to smart contracts.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants