contracts: Emit event on contract termination (#8014)

* contracts: Remove redundant bool argument from the eviction event

* contracts: Improve event documentation

* contracts: Emit event on contract termination
This commit is contained in:
Alexander Theißen
2021-02-02 11:48:35 +01:00
committed by GitHub
parent de838f9464
commit 815409f31e
4 changed files with 74 additions and 27 deletions
+2 -1
View File
@@ -582,6 +582,7 @@ where
)?; )?;
if let Some(ContractInfo::Alive(info)) = ContractInfoOf::<T>::take(&self_id) { if let Some(ContractInfo::Alive(info)) = ContractInfoOf::<T>::take(&self_id) {
Storage::<T>::queue_trie_for_deletion(&info)?; Storage::<T>::queue_trie_for_deletion(&info)?;
Contracts::<T>::deposit_event(RawEvent::Terminated(self_id, beneficiary.clone()));
Ok(()) Ok(())
} else { } else {
panic!( panic!(
@@ -671,7 +672,7 @@ where
fn deposit_event(&mut self, topics: Vec<T::Hash>, data: Vec<u8>) { fn deposit_event(&mut self, topics: Vec<T::Hash>, data: Vec<u8>) {
deposit_event::<Self::T>( deposit_event::<Self::T>(
topics, topics,
RawEvent::ContractExecution(self.ctx.self_account.clone(), data) RawEvent::ContractEmitted(self.ctx.self_account.clone(), data)
); );
} }
+39 -21
View File
@@ -756,39 +756,57 @@ decl_event! {
<T as frame_system::Config>::AccountId, <T as frame_system::Config>::AccountId,
<T as frame_system::Config>::Hash <T as frame_system::Config>::Hash
{ {
/// Contract deployed by address at the specified address. \[owner, contract\] /// Contract deployed by address at the specified address. \[deployer, contract\]
Instantiated(AccountId, AccountId), Instantiated(AccountId, AccountId),
/// Contract has been evicted and is now in tombstone state. /// Contract has been evicted and is now in tombstone state. \[contract\]
/// \[contract, tombstone\] Evicted(AccountId),
///
/// # Params
///
/// - `contract`: `AccountId`: The account ID of the evicted contract.
/// - `tombstone`: `bool`: True if the evicted contract left behind a tombstone.
Evicted(AccountId, bool),
/// Restoration for a contract has been successful. /// Contract has been terminated without leaving a tombstone.
/// \[donor, dest, code_hash, rent_allowance\] /// \[contract, beneficiary\]
/// ///
/// # Params /// # Params
/// ///
/// - `donor`: `AccountId`: Account ID of the restoring contract /// - `contract`: The contract that was terminated.
/// - `dest`: `AccountId`: Account ID of the restored contract /// - `beneficiary`: The account that received the contracts remaining balance.
/// - `code_hash`: `Hash`: Code hash of the restored contract ///
/// - `rent_allowance: `Balance`: Rent allowance of the restored contract /// # Note
///
/// The only way for a contract to be removed without a tombstone and emitting
/// this event is by calling `seal_terminate`.
Terminated(AccountId, AccountId),
/// Restoration of a contract has been successful.
/// \[restorer, dest, code_hash, rent_allowance\]
///
/// # Params
///
/// - `restorer`: Account ID of the restoring contract.
/// - `dest`: Account ID of the restored contract.
/// - `code_hash`: Code hash of the restored contract.
/// - `rent_allowance`: Rent allowance of the restored contract.
Restored(AccountId, AccountId, Hash, Balance), Restored(AccountId, AccountId, Hash, Balance),
/// Code with the specified hash has been stored. /// Code with the specified hash has been stored. \[code_hash\]
/// \[code_hash\]
CodeStored(Hash), CodeStored(Hash),
/// Triggered when the current \[schedule\] is updated. /// Triggered when the current schedule is updated.
/// \[version\]
///
/// # Params
///
/// - `version`: The version of the newly set schedule.
ScheduleUpdated(u32), ScheduleUpdated(u32),
/// An event deposited upon execution of a contract from the account. /// A custom event emitted by the contract.
/// \[account, data\] /// \[contract, data\]
ContractExecution(AccountId, Vec<u8>), ///
/// # Params
///
/// - `contract`: The contract that emitted the event.
/// - `data`: Data supplied by the contract. Metadata generated during contract
/// compilation is needed to decode it.
ContractEmitted(AccountId, Vec<u8>),
} }
} }
+1 -1
View File
@@ -261,7 +261,7 @@ where
); );
let tombstone_info = ContractInfo::Tombstone(tombstone); let tombstone_info = ContractInfo::Tombstone(tombstone);
<ContractInfoOf<T>>::insert(account, &tombstone_info); <ContractInfoOf<T>>::insert(account, &tombstone_info);
<Module<T>>::deposit_event(RawEvent::Evicted(account.clone(), true)); <Module<T>>::deposit_event(RawEvent::Evicted(account.clone()));
Ok(Some(tombstone_info)) Ok(Some(tombstone_info))
} }
Verdict::Charge { amount } => { Verdict::Charge { amount } => {
+32 -4
View File
@@ -512,7 +512,7 @@ fn instantiate_and_call_and_deposit_event() {
EventRecord { EventRecord {
phase: Phase::Initialization, phase: Phase::Initialization,
event: MetaEvent::contracts( event: MetaEvent::contracts(
RawEvent::ContractExecution(addr.clone(), vec![1, 2, 3, 4]) RawEvent::ContractEmitted(addr.clone(), vec![1, 2, 3, 4])
), ),
topics: vec![], topics: vec![],
}, },
@@ -1300,7 +1300,7 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage:
EventRecord { EventRecord {
phase: Phase::Initialization, phase: Phase::Initialization,
event: MetaEvent::contracts( event: MetaEvent::contracts(
RawEvent::Evicted(addr_bob.clone(), true) RawEvent::Evicted(addr_bob.clone())
), ),
topics: vec![], topics: vec![],
}, },
@@ -1385,7 +1385,7 @@ fn restoration(test_different_storage: bool, test_restore_to_with_dirty_storage:
pretty_assertions::assert_eq!(System::events(), vec![ pretty_assertions::assert_eq!(System::events(), vec![
EventRecord { EventRecord {
phase: Phase::Initialization, phase: Phase::Initialization,
event: MetaEvent::contracts(RawEvent::Evicted(addr_bob, true)), event: MetaEvent::contracts(RawEvent::Evicted(addr_bob)),
topics: vec![], topics: vec![],
}, },
EventRecord { EventRecord {
@@ -1633,6 +1633,7 @@ fn self_destruct_works() {
.build() .build()
.execute_with(|| { .execute_with(|| {
let _ = Balances::deposit_creating(&ALICE, 1_000_000); let _ = Balances::deposit_creating(&ALICE, 1_000_000);
let _ = Balances::deposit_creating(&DJANGO, 1_000_000);
assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm)); assert_ok!(Contracts::put_code(Origin::signed(ALICE), wasm));
// Instantiate the BOB contract. // Instantiate the BOB contract.
@@ -1652,6 +1653,9 @@ fn self_destruct_works() {
Some(ContractInfo::Alive(_)) Some(ContractInfo::Alive(_))
); );
// Drop all previous events
initialize_block(2);
// Call BOB without input data which triggers termination. // Call BOB without input data which triggers termination.
assert_matches!( assert_matches!(
Contracts::call( Contracts::call(
@@ -1664,11 +1668,35 @@ fn self_destruct_works() {
Ok(_) Ok(_)
); );
pretty_assertions::assert_eq!(System::events(), vec![
EventRecord {
phase: Phase::Initialization,
event: MetaEvent::system(
frame_system::Event::KilledAccount(addr.clone())
),
topics: vec![],
},
EventRecord {
phase: Phase::Initialization,
event: MetaEvent::balances(
pallet_balances::RawEvent::Transfer(addr.clone(), DJANGO, 100_000)
),
topics: vec![],
},
EventRecord {
phase: Phase::Initialization,
event: MetaEvent::contracts(
RawEvent::Terminated(addr.clone(), DJANGO)
),
topics: vec![],
},
]);
// Check that account is gone // Check that account is gone
assert!(ContractInfoOf::<Test>::get(&addr).is_none()); assert!(ContractInfoOf::<Test>::get(&addr).is_none());
// check that the beneficiary (django) got remaining balance // check that the beneficiary (django) got remaining balance
assert_eq!(Balances::free_balance(DJANGO), 100_000); assert_eq!(Balances::free_balance(DJANGO), 1_100_000);
}); });
} }