diff --git a/substrate/node/runtime/src/lib.rs b/substrate/node/runtime/src/lib.rs index 65eb3b8f80..1cda9e3b66 100644 --- a/substrate/node/runtime/src/lib.rs +++ b/substrate/node/runtime/src/lib.rs @@ -58,7 +58,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node"), impl_name: create_runtime_str!("substrate-node"), authoring_version: 10, - spec_version: 69, + spec_version: 70, impl_version: 70, apis: RUNTIME_API_VERSIONS, }; diff --git a/substrate/srml/contract/src/account_db.rs b/substrate/srml/contract/src/account_db.rs index b94125d6dc..df63ccc479 100644 --- a/substrate/srml/contract/src/account_db.rs +++ b/substrate/srml/contract/src/account_db.rs @@ -25,7 +25,7 @@ use rstd::cell::RefCell; use rstd::collections::btree_map::{BTreeMap, Entry}; use rstd::prelude::*; use runtime_io::blake2_256; -use runtime_primitives::traits::Zero; +use runtime_primitives::traits::{Bounded, Zero}; use srml_support::traits::{Currency, Imbalance, SignedImbalance, UpdateBalanceOutcome}; use srml_support::{storage::child, StorageMap}; use system; @@ -123,7 +123,7 @@ impl AccountDb for DirectAccountDb { storage_size: >::storage_size_offset(), trie_id: ::TrieIdGenerator::trie_id(&address), deduct_block: >::block_number(), - rent_allowance: >::zero(), + rent_allowance: >::max_value(), } } else { // No contract exist and no code_hash provided @@ -213,7 +213,7 @@ impl<'a, T: Trait> OverlayAccountDb<'a, T> { let contract = local.entry(account.clone()).or_insert_with(|| Default::default()); contract.code_hash = Some(code_hash); - contract.rent_allowance = Some(>::zero()); + contract.rent_allowance = Some(>::max_value()); Ok(()) } diff --git a/substrate/srml/contract/src/exec.rs b/substrate/srml/contract/src/exec.rs index 980fd077e9..6c55608b09 100644 --- a/substrate/srml/contract/src/exec.rs +++ b/substrate/srml/contract/src/exec.rs @@ -20,7 +20,7 @@ use crate::account_db::{AccountDb, DirectAccountDb, OverlayAccountDb}; use crate::gas::{GasMeter, Token, approx_gas_for_balance}; use rstd::prelude::*; -use runtime_primitives::traits::{CheckedAdd, CheckedSub, Zero}; +use runtime_primitives::traits::{Bounded, CheckedAdd, CheckedSub, Zero}; use srml_support::{StorageMap, traits::{WithdrawReason, Currency}}; use timestamp; @@ -641,7 +641,7 @@ where fn rent_allowance(&self) -> BalanceOf { self.ctx.overlay.get_rent_allowance(&self.ctx.self_account) - .unwrap_or(>::zero()) // Must never be triggered actually + .unwrap_or(>::max_value()) // Must never be triggered actually } } @@ -658,7 +658,7 @@ where #[cfg(test)] mod tests { use super::{ - ExecFeeToken, ExecutionContext, Ext, Loader, EmptyOutputBuf, TransferFeeKind, TransferFeeToken, + BalanceOf, ExecFeeToken, ExecutionContext, Ext, Loader, EmptyOutputBuf, TransferFeeKind, TransferFeeToken, Vm, VmExecResult, InstantiateReceipt, RawEvent, }; use crate::account_db::AccountDb; @@ -1373,7 +1373,7 @@ mod tests { let vm = MockVm::new(); let mut loader = MockLoader::empty(); let rent_allowance_ch = loader.insert(|ctx| { - assert_eq!(ctx.ext.rent_allowance(), 0); + assert_eq!(ctx.ext.rent_allowance(), >::max_value()); ctx.ext.set_rent_allowance(10); assert_eq!(ctx.ext.rent_allowance(), 10); VmExecResult::Ok diff --git a/substrate/srml/contract/src/tests.rs b/substrate/srml/contract/src/tests.rs index e18a99b832..2ce4f30503 100644 --- a/substrate/srml/contract/src/tests.rs +++ b/substrate/srml/contract/src/tests.rs @@ -21,7 +21,7 @@ use crate::account_db::{AccountDb, DirectAccountDb, OverlayAccountDb}; use crate::{ - ComputeDispatchFee, ContractAddressFor, ContractInfo, ContractInfoOf, GenesisConfig, Module, + BalanceOf, ComputeDispatchFee, ContractAddressFor, ContractInfo, ContractInfoOf, GenesisConfig, Module, RawAliveContractInfo, RawEvent, Trait, TrieId, TrieIdFromParentCounter, TrieIdGenerator, }; use assert_matches::assert_matches; @@ -614,7 +614,6 @@ const CODE_SET_RENT: &str = r#" "#; const HASH_SET_RENT: [u8; 32] = hex!("a51c2a6f3f68936d4ae9abdb93b28eedcbd0f6f39770e168f9025f0c1e7094ef"); - /// Input data for each call in set_rent code mod call { pub fn set_storage_4_byte() -> Vec { vec![] } @@ -900,3 +899,89 @@ fn removals(trigger_call: impl Fn() -> bool) { } ); } + +const CODE_CHECK_DEFAULT_RENT_ALLOWANCE: &str = r#" +(module + (import "env" "ext_rent_allowance" (func $ext_rent_allowance)) + (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) + (import "env" "ext_scratch_copy" (func $ext_scratch_copy (param i32 i32 i32))) + (import "env" "memory" (memory 1 1)) + + (func $assert (param i32) + (block $ok + (br_if $ok + (get_local 0) + ) + (unreachable) + ) + ) + + (func (export "call")) + + (func (export "deploy") + ;; fill the scratch buffer with the rent allowance. + (call $ext_rent_allowance) + + ;; assert $ext_scratch_size == 8 + (call $assert + (i32.eq + (call $ext_scratch_size) + (i32.const 8) + ) + ) + + ;; copy contents of the scratch buffer into the contract's memory. + (call $ext_scratch_copy + (i32.const 8) ;; Pointer in memory to the place where to copy. + (i32.const 0) ;; Offset from the start of the scratch buffer. + (i32.const 8) ;; Count of bytes to copy. + ) + + ;; assert that contents of the buffer is equal to >::max_value(). + (call $assert + (i64.eq + (i64.load + (i32.const 8) + ) + (i64.const 0xFFFFFFFFFFFFFFFF) + ) + ) + ) +) +"#; +const HASH_CHECK_DEFAULT_RENT_ALLOWANCE: [u8; 32] = hex!("4f9ec2b94eea522cfff10b77ef4056c631045c00978a457d283950521ecf07b6"); + +#[test] +fn default_rent_allowance_on_create() { + let wasm = wabt::wat2wasm(CODE_CHECK_DEFAULT_RENT_ALLOWANCE).unwrap(); + + with_externalities( + &mut ExtBuilder::default().existential_deposit(50).build(), + || { + // Create + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contract::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contract::create( + Origin::signed(ALICE), + 30_000, + 100_000, + HASH_CHECK_DEFAULT_RENT_ALLOWANCE.into(), + vec![], + )); + + // Check creation + let bob_contract = super::ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap(); + assert_eq!(bob_contract.rent_allowance, >::max_value()); + + // Advance blocks + System::initialize(&5, &[0u8; 32].into(), &[0u8; 32].into()); + + // Trigger rent through call + assert_ok!(Contract::call(Origin::signed(ALICE), BOB, 0, 100_000, call::null())); + + // Check contract is still alive + let bob_contract = super::ContractInfoOf::::get(BOB).unwrap().get_alive(); + assert!(bob_contract.is_some()) + } + ); +}