Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: assert events emitted from contract #216

Merged
merged 36 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
6adf1b1
refactor: fungibles pallet
Daanvdplas Aug 16, 2024
fa448bb
fix: invalid imported crates & crate visibility
chungquantin Aug 19, 2024
84c2840
fix: revert primitive error imports
chungquantin Aug 19, 2024
83a65b8
style: fix tests asset_asset parameter
Daanvdplas Aug 19, 2024
2cdc71a
test: assert events emitted from contract
chungquantin Aug 19, 2024
6cda609
Merge branch 'daan/api' into chungquantin/test-api_events
chungquantin Aug 19, 2024
aa84719
Merge branch 'daan/api' into chungquantin/test-api_events
chungquantin Aug 19, 2024
684ca91
Merge branch 'daan/api' into chungquantin/test-api_events
chungquantin Aug 27, 2024
393e1c1
refactor: api integration tests
Daanvdplas Sep 11, 2024
9320d26
taplo fmt
Daanvdplas Sep 11, 2024
4383ae0
refactor: remove clone
Daanvdplas Sep 11, 2024
0f9b166
refactor: small refactors
Daanvdplas Sep 11, 2024
29f9e57
Merge branch 'daan/api' into chungquantin/test-api_events
chungquantin Sep 12, 2024
1d2ca0e
refactor: fungibles pallet
Daanvdplas Aug 16, 2024
1752cd1
fix: invalid imported crates & crate visibility
chungquantin Aug 19, 2024
6a47735
fix: revert primitive error imports
chungquantin Aug 19, 2024
e4bbe1b
test: assert events emitted from contract
chungquantin Aug 19, 2024
1157f22
fix: resolve conflict
chungquantin Sep 13, 2024
73df148
rebase daan/api
Daanvdplas Sep 13, 2024
0122ad9
refactor: example contract
Daanvdplas Sep 13, 2024
a34a2ba
refactor: use assets module
Daanvdplas Sep 13, 2024
9accd10
fix: update events
chungquantin Sep 13, 2024
1b41af8
refactor: remove imports
chungquantin Sep 13, 2024
576f39c
Merge branch 'daan/refactor-api' into chungquantin/test-api_events
chungquantin Sep 13, 2024
45bc9d6
fix: parameter type
chungquantin Sep 13, 2024
b431b07
feat: add event emitted tests for approved and transferred
chungquantin Sep 13, 2024
1307d52
fix: comments
chungquantin Sep 13, 2024
e233e60
fix: formatting
chungquantin Sep 13, 2024
79adb97
fix: compile error
chungquantin Sep 13, 2024
c8cd349
refactor: primitivces
chungquantin Sep 13, 2024
6f64e6c
fix: resolve comments
chungquantin Sep 13, 2024
c25a5bd
fix: resolve comments
chungquantin Sep 13, 2024
9f48bdf
Merge branch 'daan/api' into chungquantin/test-api_events
chungquantin Sep 13, 2024
11508ce
fix: resolve comments
chungquantin Sep 13, 2024
0d50f2c
refactor(pop-api/fungibles): events Approve -> Approval, Destroyed ->…
peterwht Sep 13, 2024
c6d390d
refactor: less cloning
peterwht Sep 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pop-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ version = "0.0.0"
[dependencies]
ink = { version = "5.0.0", default-features = false }
pop-primitives = { path = "../primitives", default-features = false }
sp-io = { version = "31.0.0", default-features = false, features = [
sp-io = { version = "37.0.0", default-features = false, features = [
"disable_allocator",
"disable_oom",
"disable_panic_handler",
Expand Down
5 changes: 4 additions & 1 deletion pop-api/integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ log = "0.4.22"
pallet-assets = { version = "37.0.0", default-features = false }
pallet-balances = { version = "37.0.0", default-features = false }
pallet-contracts = { version = "35.0.0", default-features = false }
pop-api = { path = "../../pop-api", default-features = false, features = [
"fungibles",
] }
pop-primitives = { path = "../../primitives", default-features = false }
pop-runtime-devnet = { path = "../../runtime/devnet", default-features = false }
scale = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = [
Expand All @@ -24,7 +27,6 @@ scale = { package = "parity-scale-codec", version = "3.6.12", default-features =
sp-io = { version = "37.0.0", default-features = false }
sp-runtime = { version = "=38.0.0", default-features = false }


[features]
default = [ "std" ]
std = [
Expand All @@ -33,6 +35,7 @@ std = [
"pallet-assets/std",
"pallet-balances/std",
"pallet-contracts/std",
"pop-api/std",
"pop-primitives/std",
"pop-runtime-devnet/std",
"scale/std",
Expand Down
9 changes: 5 additions & 4 deletions pop-api/integration-tests/build.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use contract_build::{
execute, BuildArtifacts, BuildMode, BuildResult, ExecuteArgs, ManifestPath, OutputType,
Verbosity,
};
use std::{
fs,
path::{Path, PathBuf},
process,
};

use contract_build::{
execute, BuildArtifacts, BuildMode, BuildResult, ExecuteArgs, ManifestPath, OutputType,
Verbosity,
};

fn main() {
let contracts_dir = PathBuf::from("./contracts/");
let contract_dirs = match get_subcontract_directories(&contracts_dir) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![cfg_attr(not(feature = "std"), no_std, no_main)]

use pop_api::{
fungibles::{self as api},
fungibles::{self as api, events::Created},
primitives::TokenId,
StatusCode,
};
Expand All @@ -14,22 +14,23 @@ mod create_token_in_constructor {

#[ink(storage)]
pub struct Fungible {
id: TokenId,
token: TokenId,
}

impl Fungible {
#[ink(constructor, payable)]
pub fn new(id: TokenId, min_balance: Balance) -> Result<Self> {
let contract = Self { id };
let contract = Self { token: id };
// AccountId of the contract which will be set to the owner of the fungible token.
let owner = contract.env().account_id();
api::create(id, owner, min_balance)?;
contract.env().emit_event(Created { id, creator: owner, admin: owner });
Ok(contract)
}

#[ink(message)]
pub fn token_exists(&self) -> Result<bool> {
api::token_exists(self.id)
api::token_exists(self.token)
}
}
}
47 changes: 37 additions & 10 deletions pop-api/integration-tests/contracts/fungibles/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
/// 4. PSP-22 Mintable & Burnable
use ink::prelude::vec::Vec;
use pop_api::{
fungibles::{self as api},
fungibles::{
self as api,
events::{Approval, Created, DestroyStarted, MetadataCleared, MetadataSet, Transfer},
},
primitives::TokenId,
StatusCode,
};
Expand Down Expand Up @@ -60,7 +63,13 @@ mod fungibles {

#[ink(message)]
pub fn transfer(&mut self, token: TokenId, to: AccountId, value: Balance) -> Result<()> {
api::transfer(token, to, value)
api::transfer(token, to, value)?;
self.env().emit_event(Transfer {
chungquantin marked this conversation as resolved.
Show resolved Hide resolved
from: Some(self.env().account_id()),
to: Some(to),
value,
});
Ok(())
}

#[ink(message)]
Expand All @@ -73,12 +82,22 @@ mod fungibles {
// In the PSP-22 standard a `[u8]`, but the size needs to be known at compile time.
_data: Vec<u8>,
) -> Result<()> {
api::transfer_from(token, from, to, value)
api::transfer_from(token, from, to, value)?;
self.env().emit_event(Transfer { from: Some(from), to: Some(to), value });
Ok(())
}

#[ink(message)]
pub fn approve(&mut self, token: TokenId, spender: AccountId, value: Balance) -> Result<()> {
api::approve(token, spender, value)
pub fn approve(
&mut self,
token: TokenId,
spender: AccountId,
value: Balance,
) -> Result<()> {
api::approve(token, spender, value)?;
self.env()
.emit_event(Approval { owner: self.env().account_id(), spender, value });
Ok(())
}

#[ink(message)]
Expand Down Expand Up @@ -135,12 +154,16 @@ mod fungibles {
admin: AccountId,
min_balance: Balance,
) -> Result<()> {
api::create(id, admin, min_balance)
api::create(id, admin, min_balance)?;
self.env().emit_event(Created { id, creator: admin, admin });
Ok(())
}

#[ink(message)]
pub fn start_destroy(&mut self, token: TokenId) -> Result<()> {
api::start_destroy(token)
api::start_destroy(token)?;
self.env().emit_event(DestroyStarted { token });
Ok(())
}

#[ink(message)]
Expand All @@ -151,12 +174,16 @@ mod fungibles {
symbol: Vec<u8>,
decimals: u8,
) -> Result<()> {
api::set_metadata(token, name, symbol, decimals)
api::set_metadata(token, name.clone(), symbol.clone(), decimals)?;
self.env().emit_event(MetadataSet { token, name, symbol, decimals });
Ok(())
}

#[ink(message)]
pub fn clear_metadata(&self, token: TokenId) -> Result<()> {
api::clear_metadata(token)
pub fn clear_metadata(&mut self, token: TokenId) -> Result<()> {
api::clear_metadata(token)?;
self.env().emit_event(MetadataCleared { token });
Ok(())
}

#[ink(message)]
Expand Down
50 changes: 46 additions & 4 deletions pop-api/integration-tests/src/fungibles/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use pop_api::fungibles::events::{
Approval, Created, DestroyStarted, MetadataCleared, MetadataSet, Transfer,
};
use pop_primitives::{ArithmeticError::*, Error, Error::*, TokenError::*, TokenId};
use utils::*;

Expand Down Expand Up @@ -98,6 +101,11 @@ fn transfer_works() {
assert_ok!(transfer(&addr, token, BOB, amount / 2));
let balance_after_transfer = Assets::balance(token, &BOB);
assert_eq!(balance_after_transfer, balance_before_transfer + amount / 2);
// Successfully emit event.
let from = account_id_from_slice(addr.as_ref());
let to = account_id_from_slice(BOB.as_ref());
let expected = Transfer { from: Some(from), to: Some(to), value: amount / 2 }.encode();
assert_eq!(last_contract_event(), expected.as_slice());
// Transfer token to account that does not exist.
assert_eq!(transfer(&addr, token, FERDIE, amount / 4), Err(Token(CannotCreate)));
// Token is not live, i.e. frozen or being destroyed.
Expand Down Expand Up @@ -150,6 +158,11 @@ fn transfer_from_works() {
assert_ok!(transfer_from(&addr, token, ALICE, BOB, amount / 2));
let balance_after_transfer = Assets::balance(token, &BOB);
assert_eq!(balance_after_transfer, balance_before_transfer + amount / 2);
// Successfully emit event.
let from = account_id_from_slice(ALICE.as_ref());
let to = account_id_from_slice(BOB.as_ref());
let expected = Transfer { from: Some(from), to: Some(to), value: amount / 2 }.encode();
assert_eq!(last_contract_event(), expected.as_slice());
});
}

Expand All @@ -170,13 +183,23 @@ fn approve_works() {
assets::freeze(&ALICE, token);
assert_eq!(approve(&addr, token, &BOB, amount), Err(Module { index: 52, error: [16, 0] }));
assets::thaw(&ALICE, token);
// Successful approvals:
// Successful approvals.
assert_eq!(0, Assets::allowance(token, &addr, &BOB));
assert_ok!(approve(&addr, token, &BOB, amount));
assert_eq!(Assets::allowance(token, &addr, &BOB), amount);
// Successfully emit event.
let owner = account_id_from_slice(addr.as_ref());
let spender = account_id_from_slice(BOB.as_ref());
let expected = Approval { owner, spender, value: amount }.encode();
assert_eq!(last_contract_event(), expected.as_slice());
// Non-additive, sets new value.
assert_ok!(approve(&addr, token, &BOB, amount / 2));
assert_eq!(Assets::allowance(token, &addr, &BOB), amount / 2);
// Successfully emit event.
let owner = account_id_from_slice(addr.as_ref());
let spender = account_id_from_slice(BOB.as_ref());
let expected = Approval { owner, spender, value: amount / 2 }.encode();
assert_eq!(last_contract_event(), expected.as_slice());
// Token is not live, i.e. frozen or being destroyed.
assets::start_destroy(&ALICE, token);
assert_eq!(approve(&addr, token, &BOB, amount), Err(Module { index: 52, error: [16, 0] }));
Expand Down Expand Up @@ -316,6 +339,10 @@ fn create_works() {
// Create token successfully.
assert_ok!(create(&addr, TOKEN_ID, &BOB, 1));
assert_eq!(Assets::owner(TOKEN_ID), Some(addr.clone()));
// Successfully emit event.
let admin = account_id_from_slice(BOB.as_ref());
let expected = Created { id: TOKEN_ID, creator: admin, admin }.encode();
assert_eq!(last_contract_event(), expected.as_slice());
// Token ID is already taken.
assert_eq!(create(&addr, TOKEN_ID, &BOB, 1), Err(Module { index: 52, error: [5, 0] }),);
});
Expand All @@ -335,9 +362,15 @@ fn instantiate_and_create_fungible_works() {
);
// Successfully create a token when instantiating the contract.
let result_with_address = instantiate_and_create_fungible(contract, TOKEN_ID, 1);
assert_ok!(result_with_address.clone());
assert_eq!(Assets::owner(TOKEN_ID), result_with_address.ok());
let instantiator = result_with_address.clone().ok();
assert_ok!(result_with_address);
assert_eq!(&Assets::owner(TOKEN_ID), &instantiator);
assert!(Assets::asset_exists(TOKEN_ID));
// Successfully emit event.
let instantiator = account_id_from_slice(instantiator.unwrap().as_ref());
let expected =
Created { id: TOKEN_ID, creator: instantiator.clone(), admin: instantiator }.encode();
assert_eq!(last_contract_event(), expected.as_slice());
});
}

Expand All @@ -354,6 +387,9 @@ fn start_destroy_works() {
assert_eq!(start_destroy(&addr, token), Err(Module { index: 52, error: [2, 0] }),);
let token = assets::create(&addr, TOKEN_ID, 1);
assert_ok!(start_destroy(&addr, token));
// Successfully emit event.
let expected = DestroyStarted { token: TOKEN_ID }.encode();
assert_eq!(last_contract_event(), expected.as_slice());
});
}

Expand Down Expand Up @@ -393,7 +429,10 @@ fn set_metadata_works() {
Err(Module { index: 52, error: [9, 0] }),
);
// Set metadata successfully.
assert_ok!(set_metadata(&addr, TOKEN_ID, name, symbol, decimals));
assert_ok!(set_metadata(&addr, TOKEN_ID, name.clone(), symbol.clone(), decimals));
// Successfully emit event.
let expected = MetadataSet { token: TOKEN_ID, name, symbol, decimals }.encode();
assert_eq!(last_contract_event(), expected.as_slice());
// Token is not live, i.e. frozen or being destroyed.
assets::start_destroy(&addr, token);
assert_eq!(
Expand Down Expand Up @@ -427,6 +466,9 @@ fn clear_metadata_works() {
assets::set_metadata(&addr, token, name, symbol, decimals);
// Clear metadata successfully.
assert_ok!(clear_metadata(&addr, TOKEN_ID));
// Successfully emit event.
let expected = MetadataCleared { token: TOKEN_ID }.encode();
assert_eq!(last_contract_event(), expected.as_slice());
// Token is not live, i.e. frozen or being destroyed.
assets::start_destroy(&addr, token);
assert_eq!(
Expand Down
22 changes: 22 additions & 0 deletions pop-api/integration-tests/src/fungibles/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,3 +337,25 @@ pub(super) fn instantiate_and_create_fungible(
.unwrap_or_else(|_| panic!("Contract reverted: {:?}", result))
.map(|_| address)
}

/// Get the last event from pallet contracts.
pub(super) fn last_contract_event() -> Vec<u8> {
let events = System::read_events_for_pallet::<pallet_contracts::Event<Runtime>>();
let contract_events = events
.iter()
.filter_map(|event| match event {
pallet_contracts::Event::<Runtime>::ContractEmitted { data, .. } =>
Some(data.as_slice()),
_ => None,
})
.collect::<Vec<&[u8]>>();
contract_events.last().unwrap().to_vec()
}

/// Decodes a byte slice into an `AccountId` as defined in `primitives`.
///
/// This is used to resolve type mismatches between the `AccountId` in the integration tests and the
/// contract environment.
pub fn account_id_from_slice(s: &[u8; 32]) -> pop_api::primitives::AccountId {
pop_api::primitives::AccountId::decode(&mut &s[..]).expect("Should be decoded to AccountId")
}
3 changes: 2 additions & 1 deletion pop-api/src/primitives.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use ink::env::{DefaultEnvironment, Environment};
pub use pop_primitives::*;

pub(crate) type AccountId = <DefaultEnvironment as Environment>::AccountId;
// Public due to integration tests crate.
pub type AccountId = <DefaultEnvironment as Environment>::AccountId;
pub(crate) type Balance = <DefaultEnvironment as Environment>::Balance;
8 changes: 4 additions & 4 deletions pop-api/src/v0/fungibles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub mod events {

/// Event emitted when a token is created.
#[ink::event]
pub struct Create {
pub struct Created {
/// The token identifier.
#[ink(topic)]
pub id: TokenId,
Expand All @@ -115,15 +115,15 @@ pub mod events {

/// Event emitted when a token is in the process of being destroyed.
#[ink::event]
pub struct StartDestroy {
pub struct DestroyStarted {
/// The token.
#[ink(topic)]
pub token: TokenId,
}

/// Event emitted when new metadata is set for a token.
#[ink::event]
pub struct SetMetadata {
pub struct MetadataSet {
/// The token.
#[ink(topic)]
pub token: TokenId,
Expand All @@ -139,7 +139,7 @@ pub mod events {

/// Event emitted when metadata is cleared for a token.
#[ink::event]
pub struct ClearMetadata {
pub struct MetadataCleared {
/// The token.
#[ink(topic)]
pub token: TokenId,
Expand Down
2 changes: 0 additions & 2 deletions pop-api/src/v0/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use ink::env::chain_extension::ChainExtensionMethod;

use crate::{
build_extension_method,
constants::{DISPATCH, READ_STATE},
Expand Down
Loading