diff --git a/substrate/frame/contracts/tests/caller_contract.wat b/substrate/frame/contracts/fixtures/caller_contract.wat
similarity index 100%
rename from substrate/frame/contracts/tests/caller_contract.wat
rename to substrate/frame/contracts/fixtures/caller_contract.wat
diff --git a/substrate/frame/contracts/tests/check_default_rent_allowance.wat b/substrate/frame/contracts/fixtures/check_default_rent_allowance.wat
similarity index 100%
rename from substrate/frame/contracts/tests/check_default_rent_allowance.wat
rename to substrate/frame/contracts/fixtures/check_default_rent_allowance.wat
diff --git a/substrate/frame/contracts/tests/crypto_hashes.wat b/substrate/frame/contracts/fixtures/crypto_hashes.wat
similarity index 100%
rename from substrate/frame/contracts/tests/crypto_hashes.wat
rename to substrate/frame/contracts/fixtures/crypto_hashes.wat
diff --git a/substrate/frame/contracts/tests/destroy_and_transfer.wat b/substrate/frame/contracts/fixtures/destroy_and_transfer.wat
similarity index 100%
rename from substrate/frame/contracts/tests/destroy_and_transfer.wat
rename to substrate/frame/contracts/fixtures/destroy_and_transfer.wat
diff --git a/substrate/frame/contracts/tests/dispatch_call.wat b/substrate/frame/contracts/fixtures/dispatch_call.wat
similarity index 100%
rename from substrate/frame/contracts/tests/dispatch_call.wat
rename to substrate/frame/contracts/fixtures/dispatch_call.wat
diff --git a/substrate/frame/contracts/tests/dispatch_call_then_trap.wat b/substrate/frame/contracts/fixtures/dispatch_call_then_trap.wat
similarity index 100%
rename from substrate/frame/contracts/tests/dispatch_call_then_trap.wat
rename to substrate/frame/contracts/fixtures/dispatch_call_then_trap.wat
diff --git a/substrate/frame/contracts/tests/drain.wat b/substrate/frame/contracts/fixtures/drain.wat
similarity index 100%
rename from substrate/frame/contracts/tests/drain.wat
rename to substrate/frame/contracts/fixtures/drain.wat
diff --git a/substrate/frame/contracts/tests/get_runtime_storage.wat b/substrate/frame/contracts/fixtures/get_runtime_storage.wat
similarity index 100%
rename from substrate/frame/contracts/tests/get_runtime_storage.wat
rename to substrate/frame/contracts/fixtures/get_runtime_storage.wat
diff --git a/substrate/frame/contracts/tests/restoration.wat b/substrate/frame/contracts/fixtures/restoration.wat
similarity index 100%
rename from substrate/frame/contracts/tests/restoration.wat
rename to substrate/frame/contracts/fixtures/restoration.wat
diff --git a/substrate/frame/contracts/tests/return_from_start_fn.wat b/substrate/frame/contracts/fixtures/return_from_start_fn.wat
similarity index 100%
rename from substrate/frame/contracts/tests/return_from_start_fn.wat
rename to substrate/frame/contracts/fixtures/return_from_start_fn.wat
diff --git a/substrate/frame/contracts/tests/return_with_data.wat b/substrate/frame/contracts/fixtures/return_with_data.wat
similarity index 100%
rename from substrate/frame/contracts/tests/return_with_data.wat
rename to substrate/frame/contracts/fixtures/return_with_data.wat
diff --git a/substrate/frame/contracts/tests/run_out_of_gas.wat b/substrate/frame/contracts/fixtures/run_out_of_gas.wat
similarity index 100%
rename from substrate/frame/contracts/tests/run_out_of_gas.wat
rename to substrate/frame/contracts/fixtures/run_out_of_gas.wat
diff --git a/substrate/frame/contracts/tests/self_destruct.wat b/substrate/frame/contracts/fixtures/self_destruct.wat
similarity index 100%
rename from substrate/frame/contracts/tests/self_destruct.wat
rename to substrate/frame/contracts/fixtures/self_destruct.wat
diff --git a/substrate/frame/contracts/tests/self_destructing_constructor.wat b/substrate/frame/contracts/fixtures/self_destructing_constructor.wat
similarity index 100%
rename from substrate/frame/contracts/tests/self_destructing_constructor.wat
rename to substrate/frame/contracts/fixtures/self_destructing_constructor.wat
diff --git a/substrate/frame/contracts/tests/set_rent.wat b/substrate/frame/contracts/fixtures/set_rent.wat
similarity index 100%
rename from substrate/frame/contracts/tests/set_rent.wat
rename to substrate/frame/contracts/fixtures/set_rent.wat
diff --git a/substrate/frame/contracts/tests/storage_size.wat b/substrate/frame/contracts/fixtures/storage_size.wat
similarity index 100%
rename from substrate/frame/contracts/tests/storage_size.wat
rename to substrate/frame/contracts/fixtures/storage_size.wat
diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs
index 23c0417dac..944bca622b 100644
--- a/substrate/frame/contracts/src/tests.rs
+++ b/substrate/frame/contracts/src/tests.rs
@@ -14,33 +14,27 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see .
-// TODO: #1417 Add more integration tests
-// also remove the #![allow(unused)] below.
-
-#![allow(unused)]
-
use crate::{
- BalanceOf, ComputeDispatchFee, ContractAddressFor, ContractInfo, ContractInfoOf, GenesisConfig,
- Module, RawAliveContractInfo, RawEvent, Trait, TrieId, TrieIdFromParentCounter, Schedule,
- TrieIdGenerator, account_db::{AccountDb, DirectAccountDb, OverlayAccountDb},
+ BalanceOf, ContractAddressFor, ContractInfo, ContractInfoOf, GenesisConfig, Module,
+ RawAliveContractInfo, RawEvent, Trait, TrieId, Schedule, TrieIdGenerator,
+ account_db::{AccountDb, DirectAccountDb, OverlayAccountDb},
gas::Gas,
};
use assert_matches::assert_matches;
use hex_literal::*;
-use codec::{Decode, Encode, KeyedVec};
+use codec::Encode;
use sp_runtime::{
- Perbill, BuildStorage, transaction_validity::{InvalidTransaction, ValidTransaction},
- traits::{BlakeTwo256, Hash, IdentityLookup, SignedExtension, Convert},
- testing::{Digest, DigestItem, Header, UintAuthorityId, H256},
+ Perbill,
+ traits::{BlakeTwo256, Hash, IdentityLookup, Convert},
+ testing::{Header, H256},
};
use frame_support::{
- assert_ok, assert_err, assert_err_ignore_postinfo, impl_outer_dispatch, impl_outer_event,
- impl_outer_origin, parameter_types,
- storage::child, StorageMap, StorageValue, traits::{Currency, Get},
- weights::{DispatchInfo, DispatchClass, Weight, PostDispatchInfo, Pays, IdentityFee},
+ assert_ok, assert_err_ignore_postinfo, impl_outer_dispatch, impl_outer_event,
+ impl_outer_origin, parameter_types, StorageMap, StorageValue,
+ traits::{Currency, Get},
+ weights::{Weight, PostDispatchInfo, IdentityFee},
};
-use std::{cell::RefCell, sync::atomic::{AtomicUsize, Ordering}};
-use sp_core::storage::well_known_keys;
+use std::cell::RefCell;
use frame_system::{self as system, EventRecord, Phase};
mod contracts {
@@ -48,7 +42,7 @@ mod contracts {
// needs to give a name for the current crate.
// This hack is required for `impl_outer_event!`.
pub use super::super::*;
- use frame_support::impl_outer_event;
+ pub use frame_support::impl_outer_event;
}
use pallet_balances as balances;
@@ -190,8 +184,6 @@ impl ContractAddressFor for DummyContractAddressFor {
pub struct DummyTrieIdGenerator;
impl TrieIdGenerator for DummyTrieIdGenerator {
fn trie_id(account_id: &u64) -> TrieId {
- use sp_core::storage::well_known_keys;
-
let new_seed = super::AccountCounter::mutate(|v| {
*v = v.wrapping_add(1);
*v
@@ -204,13 +196,6 @@ impl TrieIdGenerator for DummyTrieIdGenerator {
}
}
-pub struct DummyComputeDispatchFee;
-impl ComputeDispatchFee for DummyComputeDispatchFee {
- fn compute_dispatch_fee(call: &Call) -> u64 {
- 69
- }
-}
-
const ALICE: u64 = 1;
const BOB: u64 = 2;
const CHARLIE: u64 = 3;
@@ -254,14 +239,24 @@ impl ExtBuilder {
}
}
-/// Generate Wasm binary and code hash from wabt source.
-fn compile_module(wabt_module: &str)
- -> Result<(Vec, ::Output), wabt::Error>
- where T: frame_system::Trait
+/// Load a given wasm module represented by a .wat file and returns a wasm binary contents along
+/// with it's hash.
+///
+/// The fixture files are located under the `fixtures/` directory.
+fn compile_module(
+ fixture_name: &str,
+) -> Result<(Vec, ::Output), wabt::Error>
+where
+ T: frame_system::Trait,
{
- let wasm = wabt::wat2wasm(wabt_module)?;
- let code_hash = T::Hashing::hash(&wasm);
- Ok((wasm, code_hash))
+ use std::fs;
+
+ let fixture_path = ["fixtures/", fixture_name, ".wat"].concat();
+ let module_wat_source =
+ fs::read_to_string(&fixture_path).expect(&format!("Unable to find {} fixture", fixture_name));
+ let wasm_binary = wabt::wat2wasm(module_wat_source)?;
+ let code_hash = T::Hashing::hash(&wasm_binary);
+ Ok((wasm_binary, code_hash))
}
// Perform a simple transfer to a non-existent account.
@@ -269,7 +264,7 @@ fn compile_module(wabt_module: &str)
#[test]
fn returns_base_call_cost() {
ExtBuilder::default().build().execute_with(|| {
- Balances::deposit_creating(&ALICE, 100_000_000);
+ let _ = Balances::deposit_creating(&ALICE, 100_000_000);
assert_eq!(
Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, Vec::new()),
@@ -292,7 +287,7 @@ fn account_removal_does_not_remove_storage() {
// Set up two accounts with free balance above the existential threshold.
{
- Balances::deposit_creating(&1, 110);
+ let _ = Balances::deposit_creating(&1, 110);
ContractInfoOf::::insert(1, &ContractInfo::Alive(RawAliveContractInfo {
trie_id: trie_id1.clone(),
storage_size: ::StorageSizeOffset::get(),
@@ -307,7 +302,7 @@ fn account_removal_does_not_remove_storage() {
overlay.set_storage(&1, key2.clone(), Some(b"2".to_vec()));
DirectAccountDb.commit(overlay.into_change_set());
- Balances::deposit_creating(&2, 110);
+ let _ = Balances::deposit_creating(&2, 110);
ContractInfoOf::::insert(2, &ContractInfo::Alive(RawAliveContractInfo {
trie_id: trie_id2.clone(),
storage_size: ::StorageSizeOffset::get(),
@@ -357,71 +352,73 @@ fn account_removal_does_not_remove_storage() {
#[test]
fn instantiate_and_call_and_deposit_event() {
- let (wasm, code_hash) = compile_module::(&load_wasm("return_from_start_fn.wat"))
- .unwrap();
+ let (wasm, code_hash) = compile_module::("return_from_start_fn").unwrap();
- ExtBuilder::default().existential_deposit(100).build().execute_with(|| {
- Balances::deposit_creating(&ALICE, 1_000_000);
+ ExtBuilder::default()
+ .existential_deposit(100)
+ .build()
+ .execute_with(|| {
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
- // Check at the end to get hash on error easily
- let creation = Contracts::instantiate(
- Origin::signed(ALICE),
- 100,
- GAS_LIMIT,
- code_hash.into(),
- vec![],
- );
+ // Check at the end to get hash on error easily
+ let creation = Contracts::instantiate(
+ Origin::signed(ALICE),
+ 100,
+ GAS_LIMIT,
+ code_hash.into(),
+ vec![],
+ );
- assert_eq!(System::events(), vec![
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::balances(
- pallet_balances::RawEvent::Endowed(BOB, 100)
- ),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::ContractExecution(BOB, vec![1, 2, 3, 4])),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)),
- topics: vec![],
- }
- ]);
+ assert_eq!(System::events(), vec![
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::balances(
+ pallet_balances::RawEvent::Endowed(BOB, 100)
+ ),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::ContractExecution(BOB, vec![1, 2, 3, 4])),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)),
+ topics: vec![],
+ }
+ ]);
- assert_ok!(creation);
- assert!(ContractInfoOf::::contains_key(BOB));
- });
+ assert_ok!(creation);
+ assert!(ContractInfoOf::::contains_key(BOB));
+ });
}
#[test]
@@ -431,118 +428,120 @@ fn dispatch_call() {
let encoded = Encode::encode(&Call::Balances(pallet_balances::Call::transfer(CHARLIE, 50)));
assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]);
- let (wasm, code_hash) = compile_module::(&load_wasm("dispatch_call.wat"))
- .unwrap();
+ let (wasm, code_hash) = compile_module::("dispatch_call").unwrap();
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- Balances::deposit_creating(&ALICE, 1_000_000);
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
- // Let's keep this assert even though it's redundant. If you ever need to update the
- // wasm source this test will fail and will show you the actual hash.
- assert_eq!(System::events(), vec![
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())),
- topics: vec![],
- },
- ]);
+ // Let's keep this assert even though it's redundant. If you ever need to update the
+ // wasm source this test will fail and will show you the actual hash.
+ assert_eq!(System::events(), vec![
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())),
+ topics: vec![],
+ },
+ ]);
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 100,
- GAS_LIMIT,
- code_hash.into(),
- vec![],
- ));
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 100,
+ GAS_LIMIT,
+ code_hash.into(),
+ vec![],
+ ));
- assert_ok!(Contracts::call(
- Origin::signed(ALICE),
- BOB, // newly created account
- 0,
- GAS_LIMIT,
- vec![],
- ));
+ assert_ok!(Contracts::call(
+ Origin::signed(ALICE),
+ BOB, // newly created account
+ 0,
+ GAS_LIMIT,
+ vec![],
+ ));
- assert_eq!(System::events(), vec![
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::balances(
- pallet_balances::RawEvent::Endowed(BOB, 100)
- ),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)),
- topics: vec![],
- },
+ assert_eq!(System::events(), vec![
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::balances(
+ pallet_balances::RawEvent::Endowed(BOB, 100)
+ ),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)),
+ topics: vec![],
+ },
- // Dispatching the call.
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::system(frame_system::RawEvent::NewAccount(CHARLIE)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::balances(
- pallet_balances::RawEvent::Endowed(CHARLIE, 50)
- ),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::balances(
- pallet_balances::RawEvent::Transfer(BOB, CHARLIE, 50)
- ),
- topics: vec![],
- },
+ // Dispatching the call.
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::system(frame_system::RawEvent::NewAccount(CHARLIE)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::balances(
+ pallet_balances::RawEvent::Endowed(CHARLIE, 50)
+ ),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::balances(
+ pallet_balances::RawEvent::Transfer(BOB, CHARLIE, 50)
+ ),
+ topics: vec![],
+ },
- // Event emitted as a result of dispatch.
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::Dispatched(BOB, true)),
- topics: vec![],
- }
- ]);
- });
+ // Event emitted as a result of dispatch.
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::Dispatched(BOB, true)),
+ topics: vec![],
+ }
+ ]);
+ });
}
#[test]
@@ -552,107 +551,108 @@ fn dispatch_call_not_dispatched_after_top_level_transaction_failure() {
let encoded = Encode::encode(&Call::Balances(pallet_balances::Call::transfer(CHARLIE, 50)));
assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]);
- let (wasm, code_hash) = compile_module::(&load_wasm("dispatch_call_then_trap.wat"))
- .unwrap();
-
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- Balances::deposit_creating(&ALICE, 1_000_000);
-
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
-
- // Let's keep this assert even though it's redundant. If you ever need to update the
- // wasm source this test will fail and will show you the actual hash.
- assert_eq!(System::events(), vec![
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())),
- topics: vec![],
- },
- ]);
-
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 100,
- GAS_LIMIT,
- code_hash.into(),
- vec![],
- ));
-
- // Call the newly instantiated contract. The contract is expected to dispatch a call
- // and then trap.
- assert_err_ignore_postinfo!(
- Contracts::call(
- Origin::signed(ALICE),
- BOB, // newly created account
- 0,
- GAS_LIMIT,
- vec![],
- ),
- "contract trapped during execution"
- );
- assert_eq!(System::events(), vec![
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::balances(
- pallet_balances::RawEvent::Endowed(BOB, 100)
- ),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)),
- topics: vec![],
- },
- // ABSENCE of events which would be caused by dispatched Balances::transfer call
- ]);
- });
-}
-
-#[test]
-fn run_out_of_gas() {
- let (wasm, code_hash) = compile_module::(&load_wasm("run_out_of_gas.wat"))
- .unwrap();
+ let (wasm, code_hash) = compile_module::("dispatch_call_then_trap").unwrap();
ExtBuilder::default()
.existential_deposit(50)
.build()
.execute_with(|| {
- Balances::deposit_creating(&ALICE, 1_000_000);
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+
+ // Let's keep this assert even though it's redundant. If you ever need to update the
+ // wasm source this test will fail and will show you the actual hash.
+ assert_eq!(System::events(), vec![
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())),
+ topics: vec![],
+ },
+ ]);
+
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 100,
+ GAS_LIMIT,
+ code_hash.into(),
+ vec![],
+ ));
+
+ // Call the newly instantiated contract. The contract is expected to dispatch a call
+ // and then trap.
+ assert_err_ignore_postinfo!(
+ Contracts::call(
+ Origin::signed(ALICE),
+ BOB, // newly created account
+ 0,
+ GAS_LIMIT,
+ vec![],
+ ),
+ "contract trapped during execution"
+ );
+ assert_eq!(System::events(), vec![
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::system(frame_system::RawEvent::NewAccount(BOB)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::balances(
+ pallet_balances::RawEvent::Endowed(BOB, 100)
+ ),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::Transfer(ALICE, BOB, 100)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::Instantiated(ALICE, BOB)),
+ topics: vec![],
+ },
+ // ABSENCE of events which would be caused by dispatched Balances::transfer call
+ ]);
+ });
+}
+
+#[test]
+fn run_out_of_gas() {
+ let (wasm, code_hash) = compile_module::("run_out_of_gas").unwrap();
+
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
@@ -696,60 +696,97 @@ fn test_set_rent_code_and_hash() {
let encoded = Encode::encode(&Call::Balances(pallet_balances::Call::transfer(CHARLIE, 50)));
assert_eq!(&encoded[..], &hex!("00000300000000000000C8")[..]);
- let (wasm, code_hash) = compile_module::(&load_wasm("set_rent.wat")).unwrap();
+ let (wasm, code_hash) = compile_module::("set_rent").unwrap();
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
- // If you ever need to update the wasm source this test will fail
- // and will show you the actual hash.
- assert_eq!(System::events(), vec![
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())),
- topics: vec![],
- },
- ]);
- });
+ // If you ever need to update the wasm source this test will fail
+ // and will show you the actual hash.
+ assert_eq!(System::events(), vec![
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::CodeStored(code_hash.into())),
+ topics: vec![],
+ },
+ ]);
+ });
}
#[test]
fn storage_size() {
- let (wasm, code_hash) = compile_module::(&load_wasm("set_rent.wat")).unwrap();
+ let (wasm, code_hash) = compile_module::("set_rent").unwrap();
// Storage size
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- // Create
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 30_000,
- GAS_LIMIT, code_hash.into(),
- ::Balance::from(1_000u32).encode() // rent allowance
- ));
- let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
- assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4);
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ // Create
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 30_000,
+ GAS_LIMIT,
+ code_hash.into(),
+ ::Balance::from(1_000u32).encode() // rent allowance
+ ));
+ let bob_contract = ContractInfoOf::::get(BOB)
+ .unwrap()
+ .get_alive()
+ .unwrap();
+ assert_eq!(
+ bob_contract.storage_size,
+ ::StorageSizeOffset::get() + 4
+ );
- assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::set_storage_4_byte()));
- let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
- assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4 + 4);
+ assert_ok!(Contracts::call(
+ Origin::signed(ALICE),
+ BOB,
+ 0,
+ GAS_LIMIT,
+ call::set_storage_4_byte()
+ ));
+ let bob_contract = ContractInfoOf::::get(BOB)
+ .unwrap()
+ .get_alive()
+ .unwrap();
+ assert_eq!(
+ bob_contract.storage_size,
+ ::StorageSizeOffset::get() + 4 + 4
+ );
- assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::remove_storage_4_byte()));
- let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
- assert_eq!(bob_contract.storage_size, ::StorageSizeOffset::get() + 4);
- });
+ assert_ok!(Contracts::call(
+ Origin::signed(ALICE),
+ BOB,
+ 0,
+ GAS_LIMIT,
+ call::remove_storage_4_byte()
+ ));
+ let bob_contract = ContractInfoOf::::get(BOB)
+ .unwrap()
+ .get_alive()
+ .unwrap();
+ assert_eq!(
+ bob_contract.storage_size,
+ ::StorageSizeOffset::get() + 4
+ );
+ });
}
fn initialize_block(number: u64) {
@@ -764,68 +801,71 @@ fn initialize_block(number: u64) {
#[test]
fn deduct_blocks() {
- let (wasm, code_hash) = compile_module::(&load_wasm("set_rent.wat")).unwrap();
+ let (wasm, code_hash) = compile_module::("set_rent").unwrap();
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- // Create
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 30_000,
- GAS_LIMIT, code_hash.into(),
- ::Balance::from(1_000u32).encode() // rent allowance
- ));
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ // Create
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 30_000,
+ GAS_LIMIT, code_hash.into(),
+ ::Balance::from(1_000u32).encode() // rent allowance
+ ));
- // Check creation
- let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
- assert_eq!(bob_contract.rent_allowance, 1_000);
+ // Check creation
+ let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
+ assert_eq!(bob_contract.rent_allowance, 1_000);
- // Advance 4 blocks
- initialize_block(5);
+ // Advance 4 blocks
+ initialize_block(5);
- // Trigger rent through call
- assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
+ // Trigger rent through call
+ assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
- // Check result
- let rent = (8 + 4 - 3) // storage size = size_offset + deploy_set_storage - deposit_offset
- * 4 // rent byte price
- * 4; // blocks to rent
- let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
- assert_eq!(bob_contract.rent_allowance, 1_000 - rent);
- assert_eq!(bob_contract.deduct_block, 5);
- assert_eq!(Balances::free_balance(BOB), 30_000 - rent);
+ // Check result
+ let rent = (8 + 4 - 3) // storage size = size_offset + deploy_set_storage - deposit_offset
+ * 4 // rent byte price
+ * 4; // blocks to rent
+ let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
+ assert_eq!(bob_contract.rent_allowance, 1_000 - rent);
+ assert_eq!(bob_contract.deduct_block, 5);
+ assert_eq!(Balances::free_balance(BOB), 30_000 - rent);
- // Advance 7 blocks more
- initialize_block(12);
+ // Advance 7 blocks more
+ initialize_block(12);
- // Trigger rent through call
- assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
+ // Trigger rent through call
+ assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
- // Check result
- let rent_2 = (8 + 4 - 2) // storage size = size_offset + deploy_set_storage - deposit_offset
- * 4 // rent byte price
- * 7; // blocks to rent
- let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
- assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2);
- assert_eq!(bob_contract.deduct_block, 12);
- assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2);
+ // Check result
+ let rent_2 = (8 + 4 - 2) // storage size = size_offset + deploy_set_storage - deposit_offset
+ * 4 // rent byte price
+ * 7; // blocks to rent
+ let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
+ assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2);
+ assert_eq!(bob_contract.deduct_block, 12);
+ assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2);
- // Second call on same block should have no effect on rent
- assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
+ // Second call on same block should have no effect on rent
+ assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
- let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
- assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2);
- assert_eq!(bob_contract.deduct_block, 12);
- assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2);
- });
+ let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
+ assert_eq!(bob_contract.rent_allowance, 1_000 - rent - rent_2);
+ assert_eq!(bob_contract.deduct_block, 12);
+ assert_eq!(Balances::free_balance(BOB), 30_000 - rent - rent_2);
+ });
}
#[test]
fn call_contract_removals() {
removals(|| {
// Call on already-removed account might fail, and this is fine.
- Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null());
+ let _ = Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null());
true
});
}
@@ -858,31 +898,34 @@ fn claim_surcharge_malus() {
/// Claim surcharge with the given trigger_call at the given blocks.
/// If `removes` is true then assert that the contract is a tombstone.
fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool) {
- let (wasm, code_hash) = compile_module::(&load_wasm("set_rent.wat")).unwrap();
+ let (wasm, code_hash) = compile_module::("set_rent").unwrap();
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- // Create
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 100,
- GAS_LIMIT, code_hash.into(),
- ::Balance::from(1_000u32).encode() // rent allowance
- ));
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ // Create
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 100,
+ GAS_LIMIT, code_hash.into(),
+ ::Balance::from(1_000u32).encode() // rent allowance
+ ));
- // Advance blocks
- initialize_block(blocks);
+ // Advance blocks
+ initialize_block(blocks);
- // Trigger rent through call
- assert!(trigger_call());
+ // Trigger rent through call
+ assert!(trigger_call());
- if removes {
- assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some());
- } else {
- assert!(ContractInfoOf::::get(BOB).unwrap().get_alive().is_some());
- }
- });
+ if removes {
+ assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some());
+ } else {
+ assert!(ContractInfoOf::::get(BOB).unwrap().get_alive().is_some());
+ }
+ });
}
/// Test for all kind of removals for the given trigger:
@@ -890,194 +933,246 @@ fn claim_surcharge(blocks: u64, trigger_call: impl Fn() -> bool, removes: bool)
/// * if allowance is exceeded
/// * if balance is reached and balance < subsistence threshold
fn removals(trigger_call: impl Fn() -> bool) {
- let (wasm, code_hash) = compile_module::(&load_wasm("set_rent.wat")).unwrap();
+ let (wasm, code_hash) = compile_module::("set_rent").unwrap();
// Balance reached and superior to subsistence threshold
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- // Create
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 100,
- GAS_LIMIT, code_hash.into(),
- ::Balance::from(1_000u32).encode() // rent allowance
- ));
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ // Create
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 100,
+ GAS_LIMIT, code_hash.into(),
+ ::Balance::from(1_000u32).encode() // rent allowance
+ ));
- let subsistence_threshold = 50 /*existential_deposit*/ + 16 /*tombstone_deposit*/;
+ let subsistence_threshold = 50 /*existential_deposit*/ + 16 /*tombstone_deposit*/;
- // Trigger rent must have no effect
- assert!(trigger_call());
- assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000);
- assert_eq!(Balances::free_balance(BOB), 100);
+ // Trigger rent must have no effect
+ assert!(trigger_call());
+ assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000);
+ assert_eq!(Balances::free_balance(BOB), 100);
- // Advance blocks
- initialize_block(10);
+ // Advance blocks
+ initialize_block(10);
- // Trigger rent through call
- assert!(trigger_call());
- assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some());
- assert_eq!(Balances::free_balance(BOB), subsistence_threshold);
+ // Trigger rent through call
+ assert!(trigger_call());
+ assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some());
+ assert_eq!(Balances::free_balance(BOB), subsistence_threshold);
- // Advance blocks
- initialize_block(20);
+ // Advance blocks
+ initialize_block(20);
- // Trigger rent must have no effect
- assert!(trigger_call());
- assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some());
- assert_eq!(Balances::free_balance(BOB), subsistence_threshold);
- });
+ // Trigger rent must have no effect
+ assert!(trigger_call());
+ assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some());
+ assert_eq!(Balances::free_balance(BOB), subsistence_threshold);
+ });
// Allowance exceeded
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- // Create
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 1_000,
- GAS_LIMIT, code_hash.into(),
- ::Balance::from(100u32).encode() // rent allowance
- ));
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ // Create
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 1_000,
+ GAS_LIMIT,
+ code_hash.into(),
+ ::Balance::from(100u32).encode() // rent allowance
+ ));
- // Trigger rent must have no effect
- assert!(trigger_call());
- assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 100);
- assert_eq!(Balances::free_balance(BOB), 1_000);
+ // Trigger rent must have no effect
+ assert!(trigger_call());
+ assert_eq!(
+ ContractInfoOf::::get(BOB)
+ .unwrap()
+ .get_alive()
+ .unwrap()
+ .rent_allowance,
+ 100
+ );
+ assert_eq!(Balances::free_balance(BOB), 1_000);
- // Advance blocks
- initialize_block(10);
+ // Advance blocks
+ initialize_block(10);
- // Trigger rent through call
- assert!(trigger_call());
- assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some());
- // Balance should be initial balance - initial rent_allowance
- assert_eq!(Balances::free_balance(BOB), 900);
+ // Trigger rent through call
+ assert!(trigger_call());
+ assert!(ContractInfoOf::::get(BOB)
+ .unwrap()
+ .get_tombstone()
+ .is_some());
+ // Balance should be initial balance - initial rent_allowance
+ assert_eq!(Balances::free_balance(BOB), 900);
- // Advance blocks
- initialize_block(20);
+ // Advance blocks
+ initialize_block(20);
- // Trigger rent must have no effect
- assert!(trigger_call());
- assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some());
- assert_eq!(Balances::free_balance(BOB), 900);
- });
+ // Trigger rent must have no effect
+ assert!(trigger_call());
+ assert!(ContractInfoOf::::get(BOB)
+ .unwrap()
+ .get_tombstone()
+ .is_some());
+ assert_eq!(Balances::free_balance(BOB), 900);
+ });
// Balance reached and inferior to subsistence threshold
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- // Create
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 50+Balances::minimum_balance(),
- GAS_LIMIT, code_hash.into(),
- ::Balance::from(1_000u32).encode() // rent allowance
- ));
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ // Create
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 50 + Balances::minimum_balance(),
+ GAS_LIMIT,
+ code_hash.into(),
+ ::Balance::from(1_000u32).encode() // rent allowance
+ ));
- // Trigger rent must have no effect
- assert!(trigger_call());
- assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000);
- assert_eq!(Balances::free_balance(BOB), 50 + Balances::minimum_balance());
+ // Trigger rent must have no effect
+ assert!(trigger_call());
+ assert_eq!(
+ ContractInfoOf::::get(BOB)
+ .unwrap()
+ .get_alive()
+ .unwrap()
+ .rent_allowance,
+ 1_000
+ );
+ assert_eq!(
+ Balances::free_balance(BOB),
+ 50 + Balances::minimum_balance()
+ );
- // Transfer funds
- assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::transfer()));
- assert_eq!(ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap().rent_allowance, 1_000);
- assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance());
+ // Transfer funds
+ assert_ok!(Contracts::call(
+ Origin::signed(ALICE),
+ BOB,
+ 0,
+ GAS_LIMIT,
+ call::transfer()
+ ));
+ assert_eq!(
+ ContractInfoOf::::get(BOB)
+ .unwrap()
+ .get_alive()
+ .unwrap()
+ .rent_allowance,
+ 1_000
+ );
+ assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance());
- // Advance blocks
- initialize_block(10);
+ // Advance blocks
+ initialize_block(10);
- // Trigger rent through call
- assert!(trigger_call());
- assert!(ContractInfoOf::::get(BOB).is_none());
- assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance());
+ // Trigger rent through call
+ assert!(trigger_call());
+ assert!(ContractInfoOf::::get(BOB).is_none());
+ assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance());
- // Advance blocks
- initialize_block(20);
+ // Advance blocks
+ initialize_block(20);
- // Trigger rent must have no effect
- assert!(trigger_call());
- assert!(ContractInfoOf::::get(BOB).is_none());
- assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance());
- });
+ // Trigger rent must have no effect
+ assert!(trigger_call());
+ assert!(ContractInfoOf::::get(BOB).is_none());
+ assert_eq!(Balances::free_balance(BOB), Balances::minimum_balance());
+ });
}
#[test]
fn call_removed_contract() {
- let (wasm, code_hash) = compile_module::(&load_wasm("set_rent.wat")).unwrap();
+ let (wasm, code_hash) = compile_module::("set_rent").unwrap();
// Balance reached and superior to subsistence threshold
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- // Create
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 100,
- GAS_LIMIT, code_hash.into(),
- ::Balance::from(1_000u32).encode() // rent allowance
- ));
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ // Create
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm.clone()));
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 100,
+ GAS_LIMIT, code_hash.into(),
+ ::Balance::from(1_000u32).encode() // rent allowance
+ ));
- // Calling contract should succeed.
- assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
+ // Calling contract should succeed.
+ assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
- // Advance blocks
- initialize_block(10);
+ // Advance blocks
+ initialize_block(10);
- // Calling contract should remove contract and fail.
- assert_err_ignore_postinfo!(
- Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()),
- "contract has been evicted"
- );
- // Calling a contract that is about to evict shall emit an event.
- assert_eq!(System::events(), vec![
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::Evicted(BOB, true)),
- topics: vec![],
- },
- ]);
+ // Calling contract should remove contract and fail.
+ assert_err_ignore_postinfo!(
+ Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()),
+ "contract has been evicted"
+ );
+ // Calling a contract that is about to evict shall emit an event.
+ assert_eq!(System::events(), vec![
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::Evicted(BOB, true)),
+ topics: vec![],
+ },
+ ]);
- // Subsequent contract calls should also fail.
- assert_err_ignore_postinfo!(
- Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()),
- "contract has been evicted"
- );
- })
+ // Subsequent contract calls should also fail.
+ assert_err_ignore_postinfo!(
+ Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()),
+ "contract has been evicted"
+ );
+ })
}
#[test]
fn default_rent_allowance_on_instantiate() {
- let (wasm, code_hash) = compile_module::(
- &load_wasm("check_default_rent_allowance.wat")).unwrap();
+ let (wasm, code_hash) = compile_module::("check_default_rent_allowance").unwrap();
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- // Create
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 30_000,
- GAS_LIMIT,
- code_hash.into(),
- vec![],
- ));
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ // Create
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 30_000,
+ GAS_LIMIT,
+ code_hash.into(),
+ vec![],
+ ));
- // Check creation
- let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
- assert_eq!(bob_contract.rent_allowance, >::max_value());
+ // Check creation
+ let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
+ assert_eq!(bob_contract.rent_allowance, >::max_value());
- // Advance blocks
- initialize_block(5);
+ // Advance blocks
+ initialize_block(5);
- // Trigger rent through call
- assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
+ // Trigger rent through call
+ assert_ok!(Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()));
- // Check contract is still alive
- let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive();
- assert!(bob_contract.is_some())
- });
+ // Check contract is still alive
+ let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive();
+ assert!(bob_contract.is_some())
+ });
}
#[test]
@@ -1101,571 +1196,586 @@ fn restoration_success() {
}
fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage: bool) {
- let (set_rent_wasm, set_rent_code_hash) =
- compile_module::(&load_wasm("set_rent.wat")).unwrap();
- let (restoration_wasm, restoration_code_hash) =
- compile_module::(&load_wasm("restoration.wat")).unwrap();
+ let (set_rent_wasm, set_rent_code_hash) = compile_module::("set_rent").unwrap();
+ let (restoration_wasm, restoration_code_hash) = compile_module::("restoration").unwrap();
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), restoration_wasm));
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), set_rent_wasm));
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), restoration_wasm));
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), set_rent_wasm));
- // If you ever need to update the wasm source this test will fail
- // and will show you the actual hash.
- assert_eq!(System::events(), vec![
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::CodeStored(restoration_code_hash.into())),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::CodeStored(set_rent_code_hash.into())),
- topics: vec![],
- },
- ]);
-
- // Create an account with address `BOB` with code `CODE_SET_RENT`.
- // The input parameter sets the rent allowance to 0.
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 30_000,
- GAS_LIMIT,
- set_rent_code_hash.into(),
- ::Balance::from(0u32).encode()
- ));
-
- // Check if `BOB` was created successfully and that the rent allowance is
- // set to 0.
- let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
- assert_eq!(bob_contract.rent_allowance, 0);
-
- if test_different_storage {
- assert_ok!(Contracts::call(
- Origin::signed(ALICE),
- BOB, 0, GAS_LIMIT,
- call::set_storage_4_byte())
- );
- }
-
- // Advance 4 blocks, to the 5th.
- initialize_block(5);
-
- /// Preserve `BOB`'s code hash for later introspection.
- let bob_code_hash = ContractInfoOf::::get(BOB).unwrap()
- .get_alive().unwrap().code_hash;
- // Call `BOB`, which makes it pay rent. Since the rent allowance is set to 0
- // we expect that it will get removed leaving tombstone.
- assert_err_ignore_postinfo!(
- Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()),
- "contract has been evicted"
- );
- assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some());
- assert_eq!(System::events(), vec![
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(
- RawEvent::Evicted(BOB.clone(), true)
- ),
- topics: vec![],
- },
- ]);
-
- /// Create another account with the address `DJANGO` with `CODE_RESTORATION`.
- ///
- /// Note that we can't use `ALICE` for creating `DJANGO` so we create yet another
- /// account `CHARLIE` and create `DJANGO` with it.
- Balances::deposit_creating(&CHARLIE, 1_000_000);
- assert_ok!(Contracts::instantiate(
- Origin::signed(CHARLIE),
- 30_000,
- GAS_LIMIT,
- restoration_code_hash.into(),
- ::Balance::from(0u32).encode()
- ));
-
- // Before performing a call to `DJANGO` save its original trie id.
- let django_trie_id = ContractInfoOf::::get(DJANGO).unwrap()
- .get_alive().unwrap().trie_id;
-
- if !test_restore_to_with_dirty_storage {
- // Advance 1 block, to the 6th.
- initialize_block(6);
- }
-
- // Perform a call to `DJANGO`. This should either perform restoration successfully or
- // fail depending on the test parameters.
- assert_ok!(Contracts::call(
- Origin::signed(ALICE),
- DJANGO,
- 0,
- GAS_LIMIT,
- vec![],
- ));
-
- if test_different_storage || test_restore_to_with_dirty_storage {
- // Parametrization of the test imply restoration failure. Check that `DJANGO` aka
- // restoration contract is still in place and also that `BOB` doesn't exist.
- assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some());
- let django_contract = ContractInfoOf::::get(DJANGO).unwrap()
- .get_alive().unwrap();
- assert_eq!(django_contract.storage_size, 16);
- assert_eq!(django_contract.trie_id, django_trie_id);
- assert_eq!(django_contract.deduct_block, System::block_number());
- match (test_different_storage, test_restore_to_with_dirty_storage) {
- (true, false) => {
- assert_eq!(System::events(), vec![
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(
- RawEvent::Restored(DJANGO, BOB, bob_code_hash, 50, false)
- ),
- topics: vec![],
- },
- ]);
- }
- (_, true) => {
- assert_eq!(System::events(), vec![
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::Evicted(BOB, true)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::system(frame_system::RawEvent::NewAccount(CHARLIE)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(CHARLIE, 1_000_000)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::system(frame_system::RawEvent::NewAccount(DJANGO)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(DJANGO, 30_000)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::Transfer(CHARLIE, DJANGO, 30_000)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::Instantiated(CHARLIE, DJANGO)),
- topics: vec![],
- },
- EventRecord {
- phase: Phase::Initialization,
- event: MetaEvent::contracts(RawEvent::Restored(
- DJANGO,
- BOB,
- bob_code_hash,
- 50,
- false,
- )),
- topics: vec![],
- },
- ]);
- }
- _ => unreachable!(),
- }
- } else {
- // Here we expect that the restoration is succeeded. Check that the restoration
- // contract `DJANGO` ceased to exist and that `BOB` returned back.
- println!("{:?}", ContractInfoOf::::get(BOB));
- let bob_contract = ContractInfoOf::::get(BOB).unwrap()
- .get_alive().unwrap();
- assert_eq!(bob_contract.rent_allowance, 50);
- assert_eq!(bob_contract.storage_size, 12);
- assert_eq!(bob_contract.trie_id, django_trie_id);
- assert_eq!(bob_contract.deduct_block, System::block_number());
- assert!(ContractInfoOf::::get(DJANGO).is_none());
+ // If you ever need to update the wasm source this test will fail
+ // and will show you the actual hash.
assert_eq!(System::events(), vec![
EventRecord {
phase: Phase::Initialization,
- event: MetaEvent::system(system::RawEvent::KilledAccount(DJANGO)),
+ event: MetaEvent::system(frame_system::RawEvent::NewAccount(1)),
topics: vec![],
},
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(1, 1_000_000)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::CodeStored(restoration_code_hash.into())),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::CodeStored(set_rent_code_hash.into())),
+ topics: vec![],
+ },
+ ]);
+
+ // Create an account with address `BOB` with code `CODE_SET_RENT`.
+ // The input parameter sets the rent allowance to 0.
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 30_000,
+ GAS_LIMIT,
+ set_rent_code_hash.into(),
+ ::Balance::from(0u32).encode()
+ ));
+
+ // Check if `BOB` was created successfully and that the rent allowance is
+ // set to 0.
+ let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
+ assert_eq!(bob_contract.rent_allowance, 0);
+
+ if test_different_storage {
+ assert_ok!(Contracts::call(
+ Origin::signed(ALICE),
+ BOB, 0, GAS_LIMIT,
+ call::set_storage_4_byte())
+ );
+ }
+
+ // Advance 4 blocks, to the 5th.
+ initialize_block(5);
+
+ // Preserve `BOB`'s code hash for later introspection.
+ let bob_code_hash = ContractInfoOf::::get(BOB).unwrap()
+ .get_alive().unwrap().code_hash;
+ // Call `BOB`, which makes it pay rent. Since the rent allowance is set to 0
+ // we expect that it will get removed leaving tombstone.
+ assert_err_ignore_postinfo!(
+ Contracts::call(Origin::signed(ALICE), BOB, 0, GAS_LIMIT, call::null()),
+ "contract has been evicted"
+ );
+ assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some());
+ assert_eq!(System::events(), vec![
EventRecord {
phase: Phase::Initialization,
event: MetaEvent::contracts(
- RawEvent::Restored(DJANGO, BOB, bob_contract.code_hash, 50, true)
+ RawEvent::Evicted(BOB.clone(), true)
),
topics: vec![],
},
]);
- }
- });
+
+ // Create another account with the address `DJANGO` with `CODE_RESTORATION`.
+ //
+ // Note that we can't use `ALICE` for creating `DJANGO` so we create yet another
+ // account `CHARLIE` and create `DJANGO` with it.
+ let _ = Balances::deposit_creating(&CHARLIE, 1_000_000);
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(CHARLIE),
+ 30_000,
+ GAS_LIMIT,
+ restoration_code_hash.into(),
+ ::Balance::from(0u32).encode()
+ ));
+
+ // Before performing a call to `DJANGO` save its original trie id.
+ let django_trie_id = ContractInfoOf::::get(DJANGO).unwrap()
+ .get_alive().unwrap().trie_id;
+
+ if !test_restore_to_with_dirty_storage {
+ // Advance 1 block, to the 6th.
+ initialize_block(6);
+ }
+
+ // Perform a call to `DJANGO`. This should either perform restoration successfully or
+ // fail depending on the test parameters.
+ assert_ok!(Contracts::call(
+ Origin::signed(ALICE),
+ DJANGO,
+ 0,
+ GAS_LIMIT,
+ vec![],
+ ));
+
+ if test_different_storage || test_restore_to_with_dirty_storage {
+ // Parametrization of the test imply restoration failure. Check that `DJANGO` aka
+ // restoration contract is still in place and also that `BOB` doesn't exist.
+ assert!(ContractInfoOf::::get(BOB).unwrap().get_tombstone().is_some());
+ let django_contract = ContractInfoOf::::get(DJANGO).unwrap()
+ .get_alive().unwrap();
+ assert_eq!(django_contract.storage_size, 16);
+ assert_eq!(django_contract.trie_id, django_trie_id);
+ assert_eq!(django_contract.deduct_block, System::block_number());
+ match (test_different_storage, test_restore_to_with_dirty_storage) {
+ (true, false) => {
+ assert_eq!(System::events(), vec![
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(
+ RawEvent::Restored(DJANGO, BOB, bob_code_hash, 50, false)
+ ),
+ topics: vec![],
+ },
+ ]);
+ }
+ (_, true) => {
+ assert_eq!(System::events(), vec![
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::Evicted(BOB, true)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::system(frame_system::RawEvent::NewAccount(CHARLIE)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(CHARLIE, 1_000_000)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::system(frame_system::RawEvent::NewAccount(DJANGO)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::balances(pallet_balances::RawEvent::Endowed(DJANGO, 30_000)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::Transfer(CHARLIE, DJANGO, 30_000)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::Instantiated(CHARLIE, DJANGO)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(RawEvent::Restored(
+ DJANGO,
+ BOB,
+ bob_code_hash,
+ 50,
+ false,
+ )),
+ topics: vec![],
+ },
+ ]);
+ }
+ _ => unreachable!(),
+ }
+ } else {
+ // Here we expect that the restoration is succeeded. Check that the restoration
+ // contract `DJANGO` ceased to exist and that `BOB` returned back.
+ println!("{:?}", ContractInfoOf::::get(BOB));
+ let bob_contract = ContractInfoOf::::get(BOB).unwrap()
+ .get_alive().unwrap();
+ assert_eq!(bob_contract.rent_allowance, 50);
+ assert_eq!(bob_contract.storage_size, 12);
+ assert_eq!(bob_contract.trie_id, django_trie_id);
+ assert_eq!(bob_contract.deduct_block, System::block_number());
+ assert!(ContractInfoOf::::get(DJANGO).is_none());
+ assert_eq!(System::events(), vec![
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::system(system::RawEvent::KilledAccount(DJANGO)),
+ topics: vec![],
+ },
+ EventRecord {
+ phase: Phase::Initialization,
+ event: MetaEvent::contracts(
+ RawEvent::Restored(DJANGO, BOB, bob_contract.code_hash, 50, true)
+ ),
+ topics: vec![],
+ },
+ ]);
+ }
+ });
}
#[test]
fn storage_max_value_limit() {
- let (wasm, code_hash) = compile_module::(&load_wasm("storage_size.wat"))
- .unwrap();
+ let (wasm, code_hash) = compile_module::("storage_size").unwrap();
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- // Create
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 30_000,
- GAS_LIMIT,
- code_hash.into(),
- vec![],
- ));
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ // Create
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 30_000,
+ GAS_LIMIT,
+ code_hash.into(),
+ vec![],
+ ));
- // Check creation
- let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
- assert_eq!(bob_contract.rent_allowance, >::max_value());
+ // Check creation
+ let bob_contract = ContractInfoOf::::get(BOB).unwrap().get_alive().unwrap();
+ assert_eq!(bob_contract.rent_allowance, >::max_value());
- // Call contract with allowed storage value.
- assert_ok!(Contracts::call(
- Origin::signed(ALICE),
- BOB,
- 0,
- GAS_LIMIT,
- Encode::encode(&self::MaxValueSize::get()),
- ));
-
- // Call contract with too large a storage value.
- assert_err_ignore_postinfo!(
- Contracts::call(
+ // Call contract with allowed storage value.
+ assert_ok!(Contracts::call(
Origin::signed(ALICE),
BOB,
0,
GAS_LIMIT,
- Encode::encode(&(self::MaxValueSize::get() + 1)),
- ),
- "contract trapped during execution"
- );
- });
+ Encode::encode(&self::MaxValueSize::get()),
+ ));
+
+ // Call contract with too large a storage value.
+ assert_err_ignore_postinfo!(
+ Contracts::call(
+ Origin::signed(ALICE),
+ BOB,
+ 0,
+ GAS_LIMIT,
+ Encode::encode(&(self::MaxValueSize::get() + 1)),
+ ),
+ "contract trapped during execution"
+ );
+ });
}
#[test]
fn deploy_and_call_other_contract() {
- let (callee_wasm, callee_code_hash) =
- compile_module::(&load_wasm("return_with_data.wat")).unwrap();
- let (caller_wasm, caller_code_hash) =
- compile_module::(&load_wasm("caller_contract.wat")).unwrap();
+ let (callee_wasm, callee_code_hash) = compile_module::("return_with_data").unwrap();
+ let (caller_wasm, caller_code_hash) = compile_module::("caller_contract").unwrap();
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- // Create
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), callee_wasm));
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), caller_wasm));
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ // Create
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), callee_wasm));
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), caller_wasm));
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 100_000,
- GAS_LIMIT,
- caller_code_hash.into(),
- vec![],
- ));
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 100_000,
+ GAS_LIMIT,
+ caller_code_hash.into(),
+ vec![],
+ ));
- // Call BOB contract, which attempts to instantiate and call the callee contract and
- // makes various assertions on the results from those calls.
- assert_ok!(Contracts::call(
- Origin::signed(ALICE),
- BOB,
- 0,
- GAS_LIMIT,
- callee_code_hash.as_ref().to_vec(),
- ));
- });
+ // Call BOB contract, which attempts to instantiate and call the callee contract and
+ // makes various assertions on the results from those calls.
+ assert_ok!(Contracts::call(
+ Origin::signed(ALICE),
+ BOB,
+ 0,
+ GAS_LIMIT,
+ callee_code_hash.as_ref().to_vec(),
+ ));
+ });
}
#[test]
fn cannot_self_destruct_through_draning() {
- let (wasm, code_hash) = compile_module::(&load_wasm("drain.wat")).unwrap();
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+ let (wasm, code_hash) = compile_module::("drain").unwrap();
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
- // Instantiate the BOB contract.
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 100_000,
- GAS_LIMIT,
- code_hash.into(),
- vec![],
- ));
-
- // Check that the BOB contract has been instantiated.
- assert_matches!(
- ContractInfoOf::::get(BOB),
- Some(ContractInfo::Alive(_))
- );
-
- // Call BOB with no input data, forcing it to run until out-of-balance
- // and eventually trapping because below existential deposit.
- assert_err_ignore_postinfo!(
- Contracts::call(
+ // Instantiate the BOB contract.
+ assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
- BOB,
- 0,
+ 100_000,
GAS_LIMIT,
+ code_hash.into(),
vec![],
- ),
- "contract trapped during execution"
- );
- });
+ ));
+
+ // Check that the BOB contract has been instantiated.
+ assert_matches!(
+ ContractInfoOf::::get(BOB),
+ Some(ContractInfo::Alive(_))
+ );
+
+ // Call BOB with no input data, forcing it to run until out-of-balance
+ // and eventually trapping because below existential deposit.
+ assert_err_ignore_postinfo!(
+ Contracts::call(
+ Origin::signed(ALICE),
+ BOB,
+ 0,
+ GAS_LIMIT,
+ vec![],
+ ),
+ "contract trapped during execution"
+ );
+ });
}
#[test]
fn cannot_self_destruct_while_live() {
- let (wasm, code_hash) = compile_module::(&load_wasm("self_destruct.wat"))
- .unwrap();
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+ let (wasm, code_hash) = compile_module::("self_destruct").unwrap();
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
- // Instantiate the BOB contract.
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 100_000,
- GAS_LIMIT,
- code_hash.into(),
- vec![],
- ));
-
- // Check that the BOB contract has been instantiated.
- assert_matches!(
- ContractInfoOf::::get(BOB),
- Some(ContractInfo::Alive(_))
- );
-
- // Call BOB with input data, forcing it make a recursive call to itself to
- // self-destruct, resulting in a trap.
- assert_err_ignore_postinfo!(
- Contracts::call(
+ // Instantiate the BOB contract.
+ assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
- BOB,
- 0,
+ 100_000,
GAS_LIMIT,
- vec![0],
- ),
- "contract trapped during execution"
- );
+ code_hash.into(),
+ vec![],
+ ));
- // Check that BOB is still alive.
- assert_matches!(
- ContractInfoOf::::get(BOB),
- Some(ContractInfo::Alive(_))
- );
- });
+ // Check that the BOB contract has been instantiated.
+ assert_matches!(
+ ContractInfoOf::::get(BOB),
+ Some(ContractInfo::Alive(_))
+ );
+
+ // Call BOB with input data, forcing it make a recursive call to itself to
+ // self-destruct, resulting in a trap.
+ assert_err_ignore_postinfo!(
+ Contracts::call(
+ Origin::signed(ALICE),
+ BOB,
+ 0,
+ GAS_LIMIT,
+ vec![0],
+ ),
+ "contract trapped during execution"
+ );
+
+ // Check that BOB is still alive.
+ assert_matches!(
+ ContractInfoOf::::get(BOB),
+ Some(ContractInfo::Alive(_))
+ );
+ });
}
#[test]
fn self_destruct_works() {
- let (wasm, code_hash) = compile_module::(&load_wasm("self_destruct.wat"))
- .unwrap();
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+ let (wasm, code_hash) = compile_module::("self_destruct").unwrap();
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
- // Instantiate the BOB contract.
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 100_000,
- GAS_LIMIT,
- code_hash.into(),
- vec![],
- ));
-
- // Check that the BOB contract has been instantiated.
- assert_matches!(
- ContractInfoOf::::get(BOB),
- Some(ContractInfo::Alive(_))
- );
-
- // Call BOB without input data which triggers termination.
- assert_matches!(
- Contracts::call(
+ // Instantiate the BOB contract.
+ assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
- BOB,
- 0,
+ 100_000,
GAS_LIMIT,
+ code_hash.into(),
vec![],
- ),
- Ok(_)
- );
+ ));
- // Check that account is gone
- assert!(ContractInfoOf::::get(BOB).is_none());
+ // Check that the BOB contract has been instantiated.
+ assert_matches!(
+ ContractInfoOf::::get(BOB),
+ Some(ContractInfo::Alive(_))
+ );
- // check that the beneficiary (django) got remaining balance
- assert_eq!(Balances::free_balance(DJANGO), 100_000);
- });
+ // Call BOB without input data which triggers termination.
+ assert_matches!(
+ Contracts::call(
+ Origin::signed(ALICE),
+ BOB,
+ 0,
+ GAS_LIMIT,
+ vec![],
+ ),
+ Ok(_)
+ );
+
+ // Check that account is gone
+ assert!(ContractInfoOf::::get(BOB).is_none());
+
+ // check that the beneficiary (django) got remaining balance
+ assert_eq!(Balances::free_balance(DJANGO), 100_000);
+ });
}
// This tests that one contract cannot prevent another from self-destructing by sending it
// additional funds after it has been drained.
#[test]
fn destroy_contract_and_transfer_funds() {
- let (callee_wasm, callee_code_hash) =
- compile_module::(&load_wasm("self_destruct.wat")).unwrap();
- let (caller_wasm, caller_code_hash) =
- compile_module::(&load_wasm("destroy_and_transfer.wat")).unwrap();
+ let (callee_wasm, callee_code_hash) = compile_module::("self_destruct").unwrap();
+ let (caller_wasm, caller_code_hash) = compile_module::("destroy_and_transfer").unwrap();
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- // Create
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), callee_wasm));
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), caller_wasm));
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ // Create
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), callee_wasm));
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), caller_wasm));
- // This deploys the BOB contract, which in turn deploys the CHARLIE contract during
- // construction.
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 200_000,
- GAS_LIMIT,
- caller_code_hash.into(),
- callee_code_hash.as_ref().to_vec(),
- ));
+ // This deploys the BOB contract, which in turn deploys the CHARLIE contract during
+ // construction.
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 200_000,
+ GAS_LIMIT,
+ caller_code_hash.into(),
+ callee_code_hash.as_ref().to_vec(),
+ ));
- // Check that the CHARLIE contract has been instantiated.
- assert_matches!(
- ContractInfoOf::::get(CHARLIE),
- Some(ContractInfo::Alive(_))
- );
+ // Check that the CHARLIE contract has been instantiated.
+ assert_matches!(
+ ContractInfoOf::::get(CHARLIE),
+ Some(ContractInfo::Alive(_))
+ );
- // Call BOB, which calls CHARLIE, forcing CHARLIE to self-destruct.
- assert_ok!(Contracts::call(
- Origin::signed(ALICE),
- BOB,
- 0,
- GAS_LIMIT,
- CHARLIE.encode(),
- ));
+ // Call BOB, which calls CHARLIE, forcing CHARLIE to self-destruct.
+ assert_ok!(Contracts::call(
+ Origin::signed(ALICE),
+ BOB,
+ 0,
+ GAS_LIMIT,
+ CHARLIE.encode(),
+ ));
- // Check that CHARLIE has moved on to the great beyond (ie. died).
- assert!(ContractInfoOf::::get(CHARLIE).is_none());
- });
+ // Check that CHARLIE has moved on to the great beyond (ie. died).
+ assert!(ContractInfoOf::::get(CHARLIE).is_none());
+ });
}
#[test]
fn cannot_self_destruct_in_constructor() {
- let (wasm, code_hash) =
- compile_module::(&load_wasm("self_destructing_constructor.wat")).unwrap();
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+ let (wasm, code_hash) = compile_module::("self_destructing_constructor").unwrap();
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
- // Fail to instantiate the BOB because the call that is issued in the deploy
- // function exhausts all balances which puts it below the existential deposit.
- assert_err_ignore_postinfo!(
- Contracts::instantiate(
+ // Fail to instantiate the BOB because the call that is issued in the deploy
+ // function exhausts all balances which puts it below the existential deposit.
+ assert_err_ignore_postinfo!(
+ Contracts::instantiate(
+ Origin::signed(ALICE),
+ 100_000,
+ GAS_LIMIT,
+ code_hash.into(),
+ vec![],
+ ),
+ "contract trapped during execution"
+ );
+ });
+}
+
+#[test]
+fn get_runtime_storage() {
+ let (wasm, code_hash) = compile_module::("get_runtime_storage").unwrap();
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+
+ frame_support::storage::unhashed::put_raw(
+ &[1, 2, 3, 4],
+ 0x14144020u32.to_le_bytes().to_vec().as_ref()
+ );
+
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+ assert_ok!(Contracts::instantiate(
+ Origin::signed(ALICE),
+ 100,
+ GAS_LIMIT,
+ code_hash.into(),
+ vec![],
+ ));
+ assert_ok!(Contracts::call(
+ Origin::signed(ALICE),
+ BOB,
+ 0,
+ GAS_LIMIT,
+ vec![],
+ ));
+ });
+}
+
+#[test]
+fn crypto_hashes() {
+ let (wasm, code_hash) = compile_module::("crypto_hashes").unwrap();
+
+ ExtBuilder::default()
+ .existential_deposit(50)
+ .build()
+ .execute_with(|| {
+ let _ = Balances::deposit_creating(&ALICE, 1_000_000);
+ assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
+
+ // Instantiate the CRYPTO_HASHES contract.
+ assert_ok!(Contracts::instantiate(
Origin::signed(ALICE),
100_000,
GAS_LIMIT,
code_hash.into(),
vec![],
- ),
- "contract trapped during execution"
- );
- });
-}
-
-fn get_runtime_storage() {
- let (wasm, code_hash) = compile_module::(&load_wasm("get_runtime_storage.wat"))
- .unwrap();
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- Balances::deposit_creating(&ALICE, 1_000_000);
-
- frame_support::storage::unhashed::put_raw(
- &[1, 2, 3, 4],
- 0x14144020u32.to_le_bytes().to_vec().as_ref()
- );
-
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 100,
- GAS_LIMIT,
- code_hash.into(),
- vec![],
- ));
- assert_ok!(Contracts::call(
- Origin::signed(ALICE),
- BOB,
- 0,
- GAS_LIMIT,
- vec![],
- ));
- });
-}
-
-#[test]
-fn crypto_hashes() {
- let (wasm, code_hash) = compile_module::(&load_wasm("crypto_hashes.wat")).unwrap();
-
- ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
- Balances::deposit_creating(&ALICE, 1_000_000);
- assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
-
- // Instantiate the CRYPTO_HASHES contract.
- assert_ok!(Contracts::instantiate(
- Origin::signed(ALICE),
- 100_000,
- GAS_LIMIT,
- code_hash.into(),
- vec![],
- ));
- // Perform the call.
- let input = b"_DEAD_BEEF";
- use sp_io::hashing::*;
- // Wraps a hash function into a more dynamic form usable for testing.
- macro_rules! dyn_hash_fn {
- ($name:ident) => {
- Box::new(|input| $name(input).as_ref().to_vec().into_boxed_slice())
- };
- }
- // All hash functions and their associated output byte lengths.
- let test_cases: &[(Box Box<[u8]>>, usize)] = &[
- (dyn_hash_fn!(sha2_256), 32),
- (dyn_hash_fn!(keccak_256), 32),
- (dyn_hash_fn!(blake2_256), 32),
- (dyn_hash_fn!(blake2_128), 16),
- ];
- // Test the given hash functions for the input: "_DEAD_BEEF"
- for (n, (hash_fn, expected_size)) in test_cases.iter().enumerate() {
- // We offset data in the contract tables by 1.
- let mut params = vec![(n + 1) as u8];
- params.extend_from_slice(input);
- let result = >::bare_call(
- ALICE,
- BOB,
- 0,
- GAS_LIMIT,
- params,
- ).unwrap();
- assert_eq!(result.status, 0);
- let expected = hash_fn(input.as_ref());
- assert_eq!(&result.data[..*expected_size], &*expected);
- }
- })
-}
-
-fn load_wasm(file_name: &str) -> String {
- let path = ["tests/", file_name].concat();
- std::fs::read_to_string(&path).expect(&format!("Unable to read {} file", path))
+ ));
+ // Perform the call.
+ let input = b"_DEAD_BEEF";
+ use sp_io::hashing::*;
+ // Wraps a hash function into a more dynamic form usable for testing.
+ macro_rules! dyn_hash_fn {
+ ($name:ident) => {
+ Box::new(|input| $name(input).as_ref().to_vec().into_boxed_slice())
+ };
+ }
+ // All hash functions and their associated output byte lengths.
+ let test_cases: &[(Box Box<[u8]>>, usize)] = &[
+ (dyn_hash_fn!(sha2_256), 32),
+ (dyn_hash_fn!(keccak_256), 32),
+ (dyn_hash_fn!(blake2_256), 32),
+ (dyn_hash_fn!(blake2_128), 16),
+ ];
+ // Test the given hash functions for the input: "_DEAD_BEEF"
+ for (n, (hash_fn, expected_size)) in test_cases.iter().enumerate() {
+ // We offset data in the contract tables by 1.
+ let mut params = vec![(n + 1) as u8];
+ params.extend_from_slice(input);
+ let result = >::bare_call(
+ ALICE,
+ BOB,
+ 0,
+ GAS_LIMIT,
+ params,
+ ).unwrap();
+ assert_eq!(result.status, 0);
+ let expected = hash_fn(input.as_ref());
+ assert_eq!(&result.data[..*expected_size], &*expected);
+ }
+ })
}