Make automatic storage deposits resistant against changing deposit prices (#12083)

* Require `FixedPointOperand` for Balances

* Delay deposit calculation

* Make refunds pro rata of consumed storage

* Add storage migration

* Fix clippy

* Add liquidity checks

* Fixe delayed deposit limit enforcement

* Defer charges

* Import Vec

* Add try-runtime hooks for migration

* Fix warning

* Adapt to new OnRuntimeUpgrade trait

* Apply suggestions from code review

Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>

* fmt

* Apply suggestions from code review

Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>

* More suggestions from code review

Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>
This commit is contained in:
Alexander Theißen
2022-09-21 19:31:22 +02:00
committed by GitHub
parent cb82064cb8
commit 857c3bf37b
12 changed files with 957 additions and 312 deletions
+13 -10
View File
@@ -813,6 +813,15 @@ where
return Ok(output)
}
// Storage limit is enforced as late as possible (when the last frame returns) so that
// the ordering of storage accesses does not matter.
if self.frames.is_empty() {
let frame = &mut self.first_frame;
frame.contract_info.load(&frame.account_id);
let contract = frame.contract_info.as_contract();
frame.nested_storage.enforce_limit(contract)?;
}
let frame = self.top_frame();
let account_id = &frame.account_id;
match (entry_point, delegated_code_hash) {
@@ -911,12 +920,7 @@ where
// it was invalidated.
frame.contract_info.load(account_id);
let mut contract = frame.contract_info.into_contract();
prev.nested_storage.absorb(
frame.nested_storage,
&self.origin,
account_id,
contract.as_mut(),
);
prev.nested_storage.absorb(frame.nested_storage, account_id, contract.as_mut());
// In case the contract wasn't terminated we need to persist changes made to it.
if let Some(contract) = contract {
@@ -954,7 +958,6 @@ where
let mut contract = self.first_frame.contract_info.as_contract();
self.storage_meter.absorb(
mem::take(&mut self.first_frame.nested_storage),
&self.origin,
&self.first_frame.account_id,
contract.as_deref_mut(),
);
@@ -2354,10 +2357,10 @@ mod tests {
let code_bob = MockLoader::insert(Call, |ctx, _| {
if ctx.input_data[0] == 0 {
let info = ctx.ext.contract_info();
assert_eq!(info.storage_deposit, 0);
info.storage_deposit = 42;
assert_eq!(info.storage_byte_deposit, 0);
info.storage_byte_deposit = 42;
assert_eq!(ctx.ext.call(Weight::zero(), CHARLIE, 0, vec![], true), exec_trapped());
assert_eq!(ctx.ext.contract_info().storage_deposit, 42);
assert_eq!(ctx.ext.contract_info().storage_byte_deposit, 42);
}
exec_success()
});