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

fix(unmerged): contract caller as a chain extension origin #301

Open
wants to merge 4 commits into
base: chungquantin/feat-psp22_example
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 14 additions & 7 deletions extension/src/environment.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use core::fmt::Debug;

use frame_support::pallet_prelude::Weight;
use pallet_contracts::chain_extension::{BufInBufOutState, ChargedAmount, Result, State};
use pallet_contracts::{
chain_extension::{BufInBufOutState, ChargedAmount, Result, State},
Origin,
};
use sp_std::vec::Vec;

use crate::AccountIdOf;
Expand Down Expand Up @@ -168,14 +171,14 @@
type AccountId;

/// Returns a reference to the account id of the current contract.
fn address(&self) -> &Self::AccountId;
fn address(&self) -> Self::AccountId;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we changing this?

}

impl Ext for () {
type AccountId = ();

fn address(&self) -> &Self::AccountId {
&()
fn address(&self) -> Self::AccountId {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, why are we changing this?

Copy link
Collaborator Author

@chungquantin chungquantin Sep 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was changed just to test if it works (will be reverted later when we decide the next step with the extension origin). Reason why I don't add the method caller() because it will bring back stuffs that @evilrobot-01 removed before #265 that removed the Config associated type. The caller() method returns OriginFor<Config> so if we want that method, we need to revert the changed Frank made.

()

Check warning on line 181 in extension/src/environment.rs

View workflow job for this annotation

GitHub Actions / clippy

unneeded unit expression

warning: unneeded unit expression --> extension/src/environment.rs:181:3 | 181 | () | ^^ help: remove the final `()` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit = note: `#[warn(clippy::unused_unit)]` on by default
}
}

Expand All @@ -185,12 +188,16 @@
impl<'a, E: pallet_contracts::chain_extension::Ext> Ext for ExternalEnvironment<'a, E> {
type AccountId = AccountIdOf<E::T>;

fn address(&self) -> &Self::AccountId {
self.0.address()
fn address(&self) -> Self::AccountId {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not add a function caller instead? This function is to get the address and should not be changed tmo

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explained here: #301 (comment)

// TODO: Need to decide which address to return.
match self.0.caller() {
Origin::Root => self.0.address().clone(),
Origin::Signed(caller) => caller,
}
}
}

#[test]
fn default_ext_works() {
assert_eq!(().address(), &())
assert_eq!(().address(), ())
}
2 changes: 1 addition & 1 deletion extension/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
let charged = env.charge_weight(dispatch_info.weight)?;
log::debug!(target: Logger::LOG_TARGET, "pre-dispatch weight charged: charged={charged:?}");
// Contract is the origin by default.
let origin = RawOrigin::Signed(env.ext().address().clone());
let origin = RawOrigin::Signed(env.ext().address());
log::debug!(target: Logger::LOG_TARGET, "contract origin: origin={origin:?}");
let mut origin: Config::RuntimeOrigin = origin.into();
// Ensure call allowed.
Expand All @@ -80,7 +80,7 @@

/// A function for reading runtime state.
pub struct ReadState<M, C, R, D, F, RC = DefaultConverter<<R as Readable>::Result>, E = (), L = ()>(
PhantomData<(M, C, R, D, F, RC, E, L)>,

Check warning on line 83 in extension/src/functions.rs

View workflow job for this annotation

GitHub Actions / clippy

very complex type used. Consider factoring parts into `type` definitions

warning: very complex type used. Consider factoring parts into `type` definitions --> extension/src/functions.rs:83:2 | 83 | PhantomData<(M, C, R, D, F, RC, E, L)>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity = note: `#[warn(clippy::type_complexity)]` on by default
);
impl<
Matcher: Matches,
Expand Down
4 changes: 2 additions & 2 deletions extension/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,8 @@ pub(crate) struct MockExt {
impl environment::Ext for MockExt {
type AccountId = AccountIdOf<Test>;

fn address(&self) -> &Self::AccountId {
&self.address
fn address(&self) -> Self::AccountId {
self.address
}
}

Expand Down
9 changes: 4 additions & 5 deletions pop-api/examples/fungibles/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,13 @@ mod fungibles {
#[ink(constructor, payable)]
pub fn new(
id: TokenId,
// TODO: If admin is different than the contract address, `NoPermission` thrown for mint, burn
// _admin: AccountId,
admin: AccountId,
min_balance: Balance,
) -> Result<Self, PSP22Error> {
let mut contract = Self { id };
let contract_id = contract.env().account_id();
api::create(id, contract_id, min_balance).map_err(PSP22Error::from)?;
contract.emit_created_event(id, contract_id, contract_id);
api::create(id, admin, min_balance).map_err(PSP22Error::from)?;
contract.emit_created_event(id, contract_id, admin);
Ok(contract)
}
}
Expand Down Expand Up @@ -161,7 +160,7 @@ mod fungibles {
api::transfer_from(self.id, from, to, value).map_err(PSP22Error::from)?;
// Emit events.
self.emit_transfer_event(Some(caller), Some(to), value);
let allowance = self.allowance(from, to).saturating_sub(value);
let allowance = self.allowance(from, caller).saturating_sub(value);
self.emit_approval_event(from, caller, allowance);
Ok(())
}
Expand Down
50 changes: 38 additions & 12 deletions pop-api/examples/fungibles/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,18 @@ fn new_constructor_works(mut session: Session) -> Result<(), Box<dyn std::error:
&mut session,
BundleProvider::local()?,
TOKEN_ID,
ALICE,
TOKEN_MIN_BALANCE,
)?;
// Token exists after the deployment.
assert!(session.sandbox().asset_exists(&TOKEN_ID));
let contract = account_id_from_slice(contract.as_ref());
// Successfully emit event.
let expected = Created { id: TOKEN_ID, creator: contract, admin: contract }.encode();
let expected = Created {
id: TOKEN_ID,
creator: account_id_from_slice(contract.as_ref()),
admin: account_id_from_slice(ALICE.as_ref()),
}
.encode();
assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice());
Ok(())
}
Expand Down Expand Up @@ -74,6 +79,7 @@ fn balance_of_works(mut session: Session) -> Result<(), Box<dyn std::error::Erro
&mut session,
BundleProvider::local()?,
TOKEN_ID,
ALICE,
TOKEN_MIN_BALANCE,
)?;
// Mint tokens.
Expand All @@ -93,6 +99,7 @@ fn mint_works(mut session: Session) -> Result<(), Box<dyn std::error::Error>> {
&mut session,
BundleProvider::local()?,
TOKEN_ID,
ALICE,
TOKEN_MIN_BALANCE,
)?;
// Mint tokens.
Expand All @@ -117,6 +124,7 @@ fn mint_zero_value_works(mut session: Session) -> Result<(), Box<dyn std::error:
&mut session,
BundleProvider::local()?,
TOKEN_ID,
ALICE,
TOKEN_MIN_BALANCE,
)?;
// Mint tokens.
Expand All @@ -137,6 +145,7 @@ fn burn_works(mut session: Session) -> Result<(), Box<dyn std::error::Error>> {
&mut session,
BundleProvider::local()?,
TOKEN_ID,
ALICE,
TOKEN_MIN_BALANCE,
)?;
// Mint tokens.
Expand All @@ -162,6 +171,7 @@ fn burn_zero_value_works(mut session: Session) -> Result<(), Box<dyn std::error:
&mut session,
BundleProvider::local()?,
TOKEN_ID,
ALICE,
TOKEN_MIN_BALANCE,
)?;
// Burn tokens.
Expand All @@ -184,6 +194,7 @@ fn burn_fails_with_insufficient_balance(
&mut session,
BundleProvider::local()?,
TOKEN_ID,
ALICE,
TOKEN_MIN_BALANCE,
)?;
// Mint tokens.
Expand All @@ -207,6 +218,7 @@ fn transfer_works(mut session: Session) -> Result<(), Box<dyn std::error::Error>
&mut session,
BundleProvider::local()?,
TOKEN_ID,
ALICE,
TOKEN_MIN_BALANCE,
)?;
// Mint tokens.
Expand Down Expand Up @@ -239,6 +251,7 @@ fn transfer_zero_value_works(mut session: Session) -> Result<(), Box<dyn std::er
&mut session,
BundleProvider::local()?,
TOKEN_ID,
ALICE,
TOKEN_MIN_BALANCE,
)?;
assert_ok!(transfer(&mut session, ALICE, 0));
Expand All @@ -257,6 +270,7 @@ fn transfer_fails_with_insufficient_balance(
&mut session,
BundleProvider::local()?,
TOKEN_ID,
ALICE,
TOKEN_MIN_BALANCE,
)?;
// Mint tokens.
Expand All @@ -283,6 +297,7 @@ fn approve_works(mut session: Session) -> Result<(), Box<dyn std::error::Error>>
&mut session,
BundleProvider::local()?,
TOKEN_ID,
ALICE,
TOKEN_MIN_BALANCE,
)?;

Expand Down Expand Up @@ -312,6 +327,7 @@ fn increase_allowance_works(mut session: Session) -> Result<(), Box<dyn std::err
&mut session,
BundleProvider::local()?,
TOKEN_ID,
ALICE,
TOKEN_MIN_BALANCE,
)?;

Expand Down Expand Up @@ -342,6 +358,7 @@ fn decrease_allowance_works(mut session: Session) -> Result<(), Box<dyn std::err
&mut session,
BundleProvider::local()?,
TOKEN_ID,
ALICE,
TOKEN_MIN_BALANCE,
)?;

Expand Down Expand Up @@ -372,26 +389,35 @@ fn transfer_from_works(mut session: Session) -> Result<(), Box<dyn std::error::E
&mut session,
BundleProvider::local()?,
TOKEN_ID,
ALICE,
TOKEN_MIN_BALANCE,
)?;

const AMOUNT: Balance = 12_000;
const AMOUNT: Balance = TOKEN_MIN_BALANCE * 4;
const TRANSFERRED: Balance = TOKEN_MIN_BALANCE * 2;
// Mint tokens.
assert_ok!(mint(&mut session, contract.clone(), AMOUNT));
// Successfully transfer from `owner`.
// Successfully transfer from `contract` by `ALICE`.
session.set_actor(contract.clone());
assert_ok!(approve(&mut session, ALICE, AMOUNT / 2));
assert_eq!(allowance(&mut session, contract.clone(), ALICE), AMOUNT / 2);
assert_ok!(approve(&mut session, ALICE, AMOUNT));
assert_eq!(allowance(&mut session, contract.clone(), ALICE), AMOUNT);
assert_eq!(balance_of(&mut session, ALICE), 0);
assert_eq!(balance_of(&mut session, BOB), 0);
assert_eq!(balance_of(&mut session, contract.clone()), AMOUNT);

session.set_actor(ALICE);
assert_ok!(transfer_from(&mut session, contract, BOB, AMOUNT / 2));
assert_ok!(transfer_from(&mut session, contract.clone(), BOB, TRANSFERRED));
// Successfully emit event.
let expected = Transfer {
from: Some(account_id_from_slice(ALICE.as_ref())),
to: Some(account_id_from_slice(BOB.as_ref())),
value: AMOUNT / 4,
let expected = Approval {
owner: account_id_from_slice(contract.clone().as_ref()),
spender: account_id_from_slice(ALICE.as_ref()),
value: TRANSFERRED,
}
.encode();
assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice());
// assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice());
assert_eq!(allowance(&mut session, contract.clone(), ALICE), AMOUNT - TRANSFERRED);
assert_eq!(balance_of(&mut session, ALICE), 0);
assert_eq!(balance_of(&mut session, BOB), TRANSFERRED);
assert_eq!(balance_of(&mut session, contract), AMOUNT - TRANSFERRED);
Ok(())
}
3 changes: 2 additions & 1 deletion pop-api/examples/fungibles/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,13 @@ pub(super) fn deploy_with_new_constructor(
session: &mut Session<Sandbox>,
bundle: ContractBundle,
id: TokenId,
admin: AccountId32,
min_balance: Balance,
) -> Result<AccountId32, SessionError> {
session.deploy_bundle(
bundle,
"new",
&[id.to_string(), min_balance.to_string()],
&[id.to_string(), admin.to_string(), min_balance.to_string()],
NO_SALT,
Some(INIT_VALUE),
)
Expand Down
Loading