seal: Prevent contracts from going below subsistence (#6623)

* seal: Do not allow transfers to bring total balance below subsistence deposit

This also reworks the rent system to take the total balance into account
when evaluating whether the account is above the subsistence deposit.

* Fix nits from review

* Fix typo

* Do not enforce subsistence when called from EOA

* Rename CallOrigin to TransactorKind

* Add debug asserts to check the invariants of a plain account transactor

* Fix typo

Co-authored-by: Sergei Shulepov <sergei@parity.io>

Co-authored-by: Sergei Shulepov <sergei@parity.io>
This commit is contained in:
Alexander TheißenandSergei Shulepov authored and GitHub committed 2020-07-10 12:45:31 +00:00
1 parent 64114267b2
commit efc69d8219
5 files changed
+116 -47

No files matched your search

+13 -5
View File
@@ -379,10 +379,7 @@ fn write_sandbox_output<E: Ext>(
let len: u32 = read_sandbox_memory_as(ctx, out_len_ptr, 4)?;
if len < buf_len {
ctx.trap_reason = Some(TrapReason::SupervisorError(
Error::<E::T>::OutputBufferTooSmall.into()
));
return Err(sp_sandbox::HostError);
Err(map_err(ctx, Error::<E::T>::OutputBufferTooSmall))?
}
charge_gas(
@@ -398,6 +395,17 @@ fn write_sandbox_output<E: Ext>(
Ok(())
}
/// Stores a DispatchError returned from an Ext function into the trap_reason.
///
/// This allows through supervisor generated errors to the caller.
fn map_err<E, Error>(ctx: &mut Runtime<E>, err: Error) -> sp_sandbox::HostError where
E: Ext,
Error: Into<DispatchError>,
{
ctx.trap_reason = Some(TrapReason::SupervisorError(err.into()));
sp_sandbox::HostError
}
// ***********************************************************
// * AFTER MAKING A CHANGE MAKE SURE TO UPDATE COMPLEXITY.MD *
// ***********************************************************
@@ -517,7 +525,7 @@ define_env!(Env, <E: Ext>,
let value: BalanceOf<<E as Ext>::T> =
read_sandbox_memory_as(ctx, value_ptr, value_len)?;
ctx.ext.transfer(&callee, value, ctx.gas_meter).map_err(|_| sp_sandbox::HostError)
ctx.ext.transfer(&callee, value, ctx.gas_meter).map_err(|e| map_err(ctx, e))
},
// Make a call to another contract.