Contracts Add deposit for dependencies (#14079)

* wip

* fixes

* rm comment

* join fns

* clippy

* Fix limits

* reduce diff

* fix

* fix

* fix typo

* refactor store to  use self

* refactor run to take self by value

* pass tests

* rm comment

* fixes

* fix typo

* rm

* fix fmt

* clippy

* ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts

* Update frame/contracts/src/lib.rs

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

* Update frame/contracts/src/wasm/mod.rs

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

* Update frame/contracts/src/wasm/mod.rs

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

* PR review, rm duplicate increment_refcount

* PR review

* Update frame/contracts/src/wasm/prepare.rs

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

* Add test for failing storage_deposit

* fix lint

* wip

* Delegate update take 2

* update

* fix migration

* fix migration

* doc

* fix lint

* update migration

* fix warning

* reformat comment

* regenerate weightInfo trait

* fix merge

* PR review

https://github.com/paritytech/substrate/pull/14079#discussion_r1255904563

* PR review

https://github.com/paritytech/substrate/pull/14079/files#r1257521373

* PR review remove optimisation

https://github.com/paritytech/substrate/pull/14079/files#r1263312237

* PR review fix return type

https://github.com/paritytech/substrate/pull/14079/files#r1263315804

* Apply suggestions from code review

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* PR review pass CodeInfo and update docstring

https://github.com/paritytech/substrate/pull/14079/files#r1257522327

* PR review add code_info to the executable

https://github.com/paritytech/substrate/pull/14079/files#r1263309049

* rename info -> contract_info

* Update frame/contracts/src/exec.rs

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* Update frame/contracts/fixtures/add_remove_delegate_dependency.wat

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* Update frame/contracts/src/migration/v13.rs

* fix tests

* Fmt & fix tests

* Test Result<(), _> return type

* Update frame/contracts/src/migration.rs

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* Revert "Test Result<(), _> return type"

This reverts commit a876168f2054edf84d720c666387583ccbe78dcd.

* add / update doc comments

* fix backticks

* Revert "Revert "Test Result<(), _> return type""

This reverts commit 3cbb6161d1abd9520cd9f8519b4dfbf4f29a2998.

* fix bench

* fix bench

* fix

* Update frame/contracts/src/storage/meter.rs

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* rm stale comments

* Apply suggestions from code review

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

* PR suggestion

* Add missing doc

* fx lint

* ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=dev --target_dir=substrate --pallet=pallet_contracts

* Update frame/contracts/src/lib.rs

Co-authored-by: Juan <juangirini@gmail.com>

---------

Co-authored-by: command-bot <>
Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>
Co-authored-by: Alexander Theißen <alex.theissen@me.com>
Co-authored-by: Juan <juangirini@gmail.com>
This commit is contained in:
PG Herveou
2023-07-26 14:09:02 +02:00
committed by GitHub
parent 47bb475d6d
commit 5a5b1df69b
14 changed files with 3956 additions and 2798 deletions
+451 -293
View File
@@ -18,14 +18,16 @@
use crate::{
gas::GasMeter,
storage::{self, DepositAccount, WriteOutcome},
BalanceOf, CodeHash, Config, ContractInfo, ContractInfoOf, DebugBufferVec, Determinism, Error,
Event, Nonce, Origin, Pallet as Contracts, Schedule, System, LOG_TARGET,
BalanceOf, CodeHash, CodeInfo, CodeInfoOf, Config, ContractInfo, ContractInfoOf,
DebugBufferVec, Determinism, Error, Event, Nonce, Origin, Pallet as Contracts, Schedule,
System, WasmBlob, LOG_TARGET,
};
use frame_support::{
crypto::ecdsa::ECDSAExt,
dispatch::{
fmt::Debug, DispatchError, DispatchResult, DispatchResultWithPostInfo, Dispatchable,
},
ensure,
storage::{with_transaction, TransactionOutcome},
traits::{
tokens::{Fortitude::Polite, Preservation::Expendable},
@@ -35,11 +37,12 @@ use frame_support::{
Blake2_128Concat, BoundedVec, StorageHasher,
};
use frame_system::{pallet_prelude::BlockNumberFor, RawOrigin};
use pallet_contracts_primitives::ExecReturnValue;
use pallet_contracts_primitives::{ExecReturnValue, StorageDeposit};
use smallvec::{Array, SmallVec};
use sp_core::{
ecdsa::Public as ECDSAPublic,
sr25519::{Public as SR25519Public, Signature as SR25519Signature},
Get,
};
use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256};
use sp_runtime::traits::{Convert, Hash, Zero};
@@ -308,6 +311,35 @@ pub trait Ext: sealing::Sealed {
/// Returns a nonce that is incremented for every instantiated contract.
fn nonce(&mut self) -> u64;
/// Adds a delegate dependency to [`ContractInfo`]'s `delegate_dependencies` field.
///
/// This ensures that the delegated contract is not removed while it is still in use. It
/// increases the reference count of the code hash and charges a fraction (see
/// [`Config::CodeHashLockupDepositPercent`]) of the code deposit.
///
/// # Errors
///
/// - [`Error::<T>::MaxDelegateDependenciesReached`]
/// - [`Error::<T>::CannotAddSelfAsDelegateDependency`]
/// - [`Error::<T>::DelegateDependencyAlreadyExists`]
fn add_delegate_dependency(
&mut self,
code_hash: CodeHash<Self::T>,
) -> Result<(), DispatchError>;
/// Removes a delegate dependency from [`ContractInfo`]'s `delegate_dependencies` field.
///
/// This is the counterpart of [`Self::add_delegate_dependency`]. It decreases the reference
/// count and refunds the deposit that was charged by [`Self::add_delegate_dependency`].
///
/// # Errors
///
/// - [`Error::<T>::DelegateDependencyNotFound`]
fn remove_delegate_dependency(
&mut self,
code_hash: &CodeHash<Self::T>,
) -> Result<(), DispatchError>;
}
/// Describes the different functions that can be exported by an [`Executable`].
@@ -365,6 +397,9 @@ pub trait Executable<T: Config>: Sized {
input_data: Vec<u8>,
) -> ExecResult;
/// The code info of the executable.
fn code_info(&self) -> &CodeInfo<T>;
/// The code hash of the executable.
fn code_hash(&self) -> &CodeHash<T>;
@@ -861,6 +896,7 @@ where
origin,
&frame.account_id,
frame.contract_info.get(&frame.account_id),
executable.code_info(),
)?;
}
@@ -1259,6 +1295,14 @@ where
info.queue_trie_for_deletion();
ContractInfoOf::<T>::remove(&frame.account_id);
E::decrement_refcount(info.code_hash);
for (code_hash, deposit) in info.delegate_dependencies() {
E::decrement_refcount(*code_hash);
frame
.nested_storage
.charge_deposit(info.deposit_account().clone(), StorageDeposit::Refund(*deposit));
}
Contracts::<T>::deposit_event(
vec![T::Hashing::hash_of(&frame.account_id), T::Hashing::hash_of(&beneficiary)],
Event::Terminated {
@@ -1433,10 +1477,24 @@ where
if !E::from_storage(hash, &mut frame.nested_gas)?.is_deterministic() {
return Err(<Error<T>>::Indeterministic.into())
}
let info = frame.contract_info();
let prev_hash = info.code_hash;
info.code_hash = hash;
let code_info = CodeInfoOf::<T>::get(hash).ok_or(Error::<T>::CodeNotFound)?;
let old_base_deposit = info.storage_base_deposit();
let new_base_deposit = info.update_base_deposit(&code_info);
let deposit = StorageDeposit::Charge(new_base_deposit)
.saturating_sub(&StorageDeposit::Charge(old_base_deposit));
let deposit_account = info.deposit_account().clone();
frame.nested_storage.charge_deposit(deposit_account, deposit);
E::increment_refcount(hash)?;
let prev_hash = frame.contract_info().code_hash;
E::decrement_refcount(prev_hash);
frame.contract_info().code_hash = hash;
Contracts::<Self::T>::deposit_event(
vec![T::Hashing::hash_of(&frame.account_id), hash, prev_hash],
Event::ContractCodeUpdated {
@@ -1468,6 +1526,41 @@ where
current
}
}
fn add_delegate_dependency(
&mut self,
code_hash: CodeHash<Self::T>,
) -> Result<(), DispatchError> {
let frame = self.top_frame_mut();
let info = frame.contract_info.get(&frame.account_id);
ensure!(code_hash != info.code_hash, Error::<T>::CannotAddSelfAsDelegateDependency);
let code_info = CodeInfoOf::<T>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?;
let deposit = T::CodeHashLockupDepositPercent::get().mul_ceil(code_info.deposit());
info.add_delegate_dependency(code_hash, deposit)?;
<WasmBlob<T>>::increment_refcount(code_hash)?;
frame
.nested_storage
.charge_deposit(info.deposit_account().clone(), StorageDeposit::Charge(deposit));
Ok(())
}
fn remove_delegate_dependency(
&mut self,
code_hash: &CodeHash<Self::T>,
) -> Result<(), DispatchError> {
let frame = self.top_frame_mut();
let info = frame.contract_info.get(&frame.account_id);
let deposit = info.remove_delegate_dependency(code_hash)?;
<WasmBlob<T>>::decrement_refcount(*code_hash);
frame
.nested_storage
.charge_deposit(info.deposit_account().clone(), StorageDeposit::Refund(deposit));
Ok(())
}
}
mod sealing {
@@ -1543,6 +1636,7 @@ mod tests {
func: Rc<dyn Fn(MockCtx, &Self) -> ExecResult + 'static>,
func_type: ExportedFunction,
code_hash: CodeHash<Test>,
code_info: CodeInfo<Test>,
refcount: u64,
}
@@ -1553,6 +1647,10 @@ mod tests {
}
impl MockLoader {
fn code_hashes() -> Vec<CodeHash<Test>> {
Loader::get().map.keys().copied().collect()
}
fn insert(
func_type: ExportedFunction,
f: impl Fn(MockCtx, &MockExecutable) -> ExecResult + 'static,
@@ -1563,7 +1661,13 @@ mod tests {
loader.counter += 1;
loader.map.insert(
hash,
MockExecutable { func: Rc::new(f), func_type, code_hash: hash, refcount: 1 },
MockExecutable {
func: Rc::new(f),
func_type,
code_hash: hash,
code_info: CodeInfo::<Test>::new(ALICE),
refcount: 1,
},
);
hash
})
@@ -1633,6 +1737,10 @@ mod tests {
&self.code_hash
}
fn code_info(&self) -> &CodeInfo<Test> {
&self.code_info
}
fn code_len(&self) -> u32 {
0
}
@@ -1954,29 +2062,33 @@ mod tests {
});
// This one tests passing the input data into a contract via instantiate.
ExtBuilder::default().build().execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable = MockExecutable::from_storage(input_data_ch, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 10_000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
storage::meter::Meter::new(&contract_origin, None, min_balance).unwrap();
ExtBuilder::default()
.with_code_hashes(MockLoader::code_hashes())
.build()
.execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable =
MockExecutable::from_storage(input_data_ch, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 10_000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
storage::meter::Meter::new(&contract_origin, None, min_balance).unwrap();
let result = MockStack::run_instantiate(
ALICE,
executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
min_balance,
vec![1, 2, 3, 4],
&[],
None,
);
assert_matches!(result, Ok(_));
});
let result = MockStack::run_instantiate(
ALICE,
executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
min_balance,
vec![1, 2, 3, 4],
&[],
None,
);
assert_matches!(result, Ok(_));
});
}
#[test]
@@ -2399,43 +2511,53 @@ mod tests {
Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![80, 65, 83, 83] })
});
ExtBuilder::default().existential_deposit(15).build().execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 1000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
storage::meter::Meter::new(&contract_origin, Some(min_balance * 100), min_balance)
.unwrap();
let instantiated_contract_address = assert_matches!(
MockStack::run_instantiate(
ALICE,
executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
ExtBuilder::default()
.with_code_hashes(MockLoader::code_hashes())
.existential_deposit(15)
.build()
.execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 1000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter = storage::meter::Meter::new(
&contract_origin,
Some(min_balance * 100),
min_balance,
vec![],
&[],
None,
),
Ok((address, ref output)) if output.data == vec![80, 65, 83, 83] => address
);
)
.unwrap();
// Check that the newly created account has the expected code hash and
// there are instantiation event.
assert_eq!(
ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).unwrap(),
dummy_ch
);
assert_eq!(
&events(),
&[Event::Instantiated { deployer: ALICE, contract: instantiated_contract_address }]
);
});
let instantiated_contract_address = assert_matches!(
MockStack::run_instantiate(
ALICE,
executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
min_balance,
vec![],
&[],
None,
),
Ok((address, ref output)) if output.data == vec![80, 65, 83, 83] => address
);
// Check that the newly created account has the expected code hash and
// there are instantiation event.
assert_eq!(
ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).unwrap(),
dummy_ch
);
assert_eq!(
&events(),
&[Event::Instantiated {
deployer: ALICE,
contract: instantiated_contract_address
}]
);
});
}
#[test]
@@ -2444,36 +2566,45 @@ mod tests {
Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70, 65, 73, 76] })
});
ExtBuilder::default().existential_deposit(15).build().execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 1000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
storage::meter::Meter::new(&contract_origin, Some(min_balance * 100), min_balance)
.unwrap();
let instantiated_contract_address = assert_matches!(
MockStack::run_instantiate(
ALICE,
executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
ExtBuilder::default()
.with_code_hashes(MockLoader::code_hashes())
.existential_deposit(15)
.build()
.execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable = MockExecutable::from_storage(dummy_ch, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 1000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter = storage::meter::Meter::new(
&contract_origin,
Some(min_balance * 100),
min_balance,
vec![],
&[],
None,
),
Ok((address, ref output)) if output.data == vec![70, 65, 73, 76] => address
);
)
.unwrap();
// Check that the account has not been created.
assert!(ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).is_none());
assert!(events().is_empty());
});
let instantiated_contract_address = assert_matches!(
MockStack::run_instantiate(
ALICE,
executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
min_balance,
vec![],
&[],
None,
),
Ok((address, ref output)) if output.data == vec![70, 65, 73, 76] => address
);
// Check that the account has not been created.
assert!(
ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).is_none()
);
assert!(events().is_empty());
});
}
#[test]
@@ -2501,51 +2632,58 @@ mod tests {
}
});
ExtBuilder::default().existential_deposit(15).build().execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
let min_balance = <Test as Config>::Currency::minimum_balance();
set_balance(&ALICE, min_balance * 100);
place_contract(&BOB, instantiator_ch);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter = storage::meter::Meter::new(
&contract_origin,
Some(min_balance * 10),
min_balance * 10,
)
.unwrap();
assert_matches!(
MockStack::run_call(
contract_origin,
BOB,
&mut GasMeter::<Test>::new(GAS_LIMIT),
&mut storage_meter,
&schedule,
ExtBuilder::default()
.with_code_hashes(MockLoader::code_hashes())
.existential_deposit(15)
.build()
.execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
let min_balance = <Test as Config>::Currency::minimum_balance();
set_balance(&ALICE, min_balance * 100);
place_contract(&BOB, instantiator_ch);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter = storage::meter::Meter::new(
&contract_origin,
Some(min_balance * 10),
min_balance * 10,
vec![],
None,
Determinism::Enforced,
),
Ok(_)
);
)
.unwrap();
let instantiated_contract_address =
instantiated_contract_address.borrow().as_ref().unwrap().clone();
assert_matches!(
MockStack::run_call(
contract_origin,
BOB,
&mut GasMeter::<Test>::new(GAS_LIMIT),
&mut storage_meter,
&schedule,
min_balance * 10,
vec![],
None,
Determinism::Enforced,
),
Ok(_)
);
// Check that the newly created account has the expected code hash and
// there are instantiation event.
assert_eq!(
ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).unwrap(),
dummy_ch
);
assert_eq!(
&events(),
&[
Event::Instantiated { deployer: BOB, contract: instantiated_contract_address },
Event::Called { caller: Origin::from_account_id(ALICE), contract: BOB },
]
);
});
let instantiated_contract_address =
instantiated_contract_address.borrow().as_ref().unwrap().clone();
// Check that the newly created account has the expected code hash and
// there are instantiation event.
assert_eq!(
ContractInfo::<Test>::load_code_hash(&instantiated_contract_address).unwrap(),
dummy_ch
);
assert_eq!(
&events(),
&[
Event::Instantiated {
deployer: BOB,
contract: instantiated_contract_address
},
Event::Called { caller: Origin::from_account_id(ALICE), contract: BOB },
]
);
});
}
#[test]
@@ -2573,37 +2711,41 @@ mod tests {
}
});
ExtBuilder::default().existential_deposit(15).build().execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
set_balance(&ALICE, 1000);
set_balance(&BOB, 100);
place_contract(&BOB, instantiator_ch);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
storage::meter::Meter::new(&contract_origin, Some(200), 0).unwrap();
ExtBuilder::default()
.with_code_hashes(MockLoader::code_hashes())
.existential_deposit(15)
.build()
.execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
set_balance(&ALICE, 1000);
set_balance(&BOB, 100);
place_contract(&BOB, instantiator_ch);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
storage::meter::Meter::new(&contract_origin, Some(200), 0).unwrap();
assert_matches!(
MockStack::run_call(
contract_origin,
BOB,
&mut GasMeter::<Test>::new(GAS_LIMIT),
&mut storage_meter,
&schedule,
0,
vec![],
None,
Determinism::Enforced,
),
Ok(_)
);
assert_matches!(
MockStack::run_call(
contract_origin,
BOB,
&mut GasMeter::<Test>::new(GAS_LIMIT),
&mut storage_meter,
&schedule,
0,
vec![],
None,
Determinism::Enforced,
),
Ok(_)
);
// The contract wasn't instantiated so we don't expect to see an instantiation
// event here.
assert_eq!(
&events(),
&[Event::Called { caller: Origin::from_account_id(ALICE), contract: BOB },]
);
});
// The contract wasn't instantiated so we don't expect to see an instantiation
// event here.
assert_eq!(
&events(),
&[Event::Called { caller: Origin::from_account_id(ALICE), contract: BOB },]
);
});
}
#[test]
@@ -2613,32 +2755,37 @@ mod tests {
exec_success()
});
ExtBuilder::default().existential_deposit(15).build().execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable = MockExecutable::from_storage(terminate_ch, &mut gas_meter).unwrap();
set_balance(&ALICE, 10_000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
storage::meter::Meter::new(&contract_origin, None, 100).unwrap();
ExtBuilder::default()
.with_code_hashes(MockLoader::code_hashes())
.existential_deposit(15)
.build()
.execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable =
MockExecutable::from_storage(terminate_ch, &mut gas_meter).unwrap();
set_balance(&ALICE, 10_000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
storage::meter::Meter::new(&contract_origin, None, 100).unwrap();
assert_eq!(
MockStack::run_instantiate(
ALICE,
executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
100,
vec![],
&[],
None,
),
Err(Error::<Test>::TerminatedInConstructor.into())
);
assert_eq!(
MockStack::run_instantiate(
ALICE,
executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
100,
vec![],
&[],
None,
),
Err(Error::<Test>::TerminatedInConstructor.into())
);
assert_eq!(&events(), &[]);
});
assert_eq!(&events(), &[]);
});
}
#[test]
@@ -2714,29 +2861,32 @@ mod tests {
});
// This one tests passing the input data into a contract via instantiate.
ExtBuilder::default().build().execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable = MockExecutable::from_storage(code, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 10_000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
storage::meter::Meter::new(&contract_origin, None, min_balance).unwrap();
ExtBuilder::default()
.with_code_hashes(MockLoader::code_hashes())
.build()
.execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let executable = MockExecutable::from_storage(code, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 10_000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
storage::meter::Meter::new(&contract_origin, None, min_balance).unwrap();
let result = MockStack::run_instantiate(
ALICE,
executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
min_balance,
vec![],
&[],
None,
);
assert_matches!(result, Ok(_));
});
let result = MockStack::run_instantiate(
ALICE,
executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
min_balance,
vec![],
&[],
None,
);
assert_matches!(result, Ok(_));
});
}
#[test]
@@ -3138,75 +3288,79 @@ mod tests {
exec_success()
});
ExtBuilder::default().build().execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let fail_executable = MockExecutable::from_storage(fail_code, &mut gas_meter).unwrap();
let success_executable =
MockExecutable::from_storage(success_code, &mut gas_meter).unwrap();
let succ_fail_executable =
MockExecutable::from_storage(succ_fail_code, &mut gas_meter).unwrap();
let succ_succ_executable =
MockExecutable::from_storage(succ_succ_code, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 10_000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
storage::meter::Meter::new(&contract_origin, None, min_balance * 100).unwrap();
ExtBuilder::default()
.with_code_hashes(MockLoader::code_hashes())
.build()
.execute_with(|| {
let schedule = <Test as Config>::Schedule::get();
let min_balance = <Test as Config>::Currency::minimum_balance();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
let fail_executable =
MockExecutable::from_storage(fail_code, &mut gas_meter).unwrap();
let success_executable =
MockExecutable::from_storage(success_code, &mut gas_meter).unwrap();
let succ_fail_executable =
MockExecutable::from_storage(succ_fail_code, &mut gas_meter).unwrap();
let succ_succ_executable =
MockExecutable::from_storage(succ_succ_code, &mut gas_meter).unwrap();
set_balance(&ALICE, min_balance * 10_000);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
storage::meter::Meter::new(&contract_origin, None, min_balance * 100).unwrap();
MockStack::run_instantiate(
ALICE,
fail_executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
min_balance * 100,
vec![],
&[],
None,
)
.ok();
assert_eq!(<Nonce<Test>>::get(), 0);
MockStack::run_instantiate(
ALICE,
fail_executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
min_balance * 100,
vec![],
&[],
None,
)
.ok();
assert_eq!(<Nonce<Test>>::get(), 0);
assert_ok!(MockStack::run_instantiate(
ALICE,
success_executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
min_balance * 100,
vec![],
&[],
None,
));
assert_eq!(<Nonce<Test>>::get(), 1);
assert_ok!(MockStack::run_instantiate(
ALICE,
success_executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
min_balance * 100,
vec![],
&[],
None,
));
assert_eq!(<Nonce<Test>>::get(), 1);
assert_ok!(MockStack::run_instantiate(
ALICE,
succ_fail_executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
min_balance * 200,
vec![],
&[],
None,
));
assert_eq!(<Nonce<Test>>::get(), 2);
assert_ok!(MockStack::run_instantiate(
ALICE,
succ_fail_executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
min_balance * 200,
vec![],
&[],
None,
));
assert_eq!(<Nonce<Test>>::get(), 2);
assert_ok!(MockStack::run_instantiate(
ALICE,
succ_succ_executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
min_balance * 200,
vec![],
&[],
None,
));
assert_eq!(<Nonce<Test>>::get(), 4);
});
assert_ok!(MockStack::run_instantiate(
ALICE,
succ_succ_executable,
&mut gas_meter,
&mut storage_meter,
&schedule,
min_balance * 200,
vec![],
&[],
None,
));
assert_eq!(<Nonce<Test>>::get(), 4);
});
}
#[test]
@@ -3676,26 +3830,30 @@ mod tests {
exec_success()
});
ExtBuilder::default().build().execute_with(|| {
let min_balance = <Test as Config>::Currency::minimum_balance();
let schedule = <Test as Config>::Schedule::get();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
set_balance(&ALICE, min_balance * 1000);
place_contract(&BOB, code_hash);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter = storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
assert_ok!(MockStack::run_call(
contract_origin,
BOB,
&mut gas_meter,
&mut storage_meter,
&schedule,
0,
vec![],
None,
Determinism::Enforced
));
});
ExtBuilder::default()
.with_code_hashes(MockLoader::code_hashes())
.build()
.execute_with(|| {
let min_balance = <Test as Config>::Currency::minimum_balance();
let schedule = <Test as Config>::Schedule::get();
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
set_balance(&ALICE, min_balance * 1000);
place_contract(&BOB, code_hash);
let contract_origin = Origin::from_account_id(ALICE);
let mut storage_meter =
storage::meter::Meter::new(&contract_origin, None, 0).unwrap();
assert_ok!(MockStack::run_call(
contract_origin,
BOB,
&mut gas_meter,
&mut storage_meter,
&schedule,
0,
vec![],
None,
Determinism::Enforced
));
});
}
/// This works even though random interface is deprecated, as the check to ban deprecated