Skip to content

Commit f7ea990

Browse files
committed
show David
1 parent e14c8d0 commit f7ea990

File tree

5 files changed

+119
-14
lines changed

5 files changed

+119
-14
lines changed

integration-tests/contracts/assets/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ version = "0.1.0"
66

77
# ink! abi required for multiple constructors (fungibles)
88
[package.metadata.ink-lang]
9-
abi = "sol"
9+
abi = "all"
1010

1111
[workspace]
1212

integration-tests/contracts/assets/lib.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![cfg_attr(not(feature = "std"), no_std, no_main)]
22

3-
use ink::{abi::Sol, sol::SolErrorDecode, env::DefaultEnvironment, Address, U256, contract_ref};
3+
use ink::{prelude::string::String, abi::Sol, env::DefaultEnvironment, Address, U256, contract_ref};
44

55
/// Asset Hub ERC20 precompile index
66
pub const PRECOMPILE_INDEX: u16 = 0x0120;
@@ -30,6 +30,10 @@ pub fn prefixed_address(n: u16, prefix: u32) -> Address {
3030
Address::from(address_bytes)
3131
}
3232

33+
#[derive(ink::SolErrorDecode, ink::SolErrorEncode)]
34+
#[ink::scale_derive(Encode, Decode, TypeInfo)]
35+
pub struct Error(pub(crate) String);
36+
3337
/// Asset Hub precompile interface.
3438
#[ink::contract]
3539
pub mod asset_hub_precompile {
@@ -47,17 +51,23 @@ pub mod asset_hub_precompile {
4751
fn balanceOf(&self, account: Address) -> U256;
4852

4953
#[ink(message)]
50-
fn transfer(&mut self, to: Address, value: U256) -> bool;
54+
fn transfer(&mut self, to: Address, value: U256) -> Result<bool, Error>;
5155

5256
#[ink(message)]
5357
fn allowance(&self, owner: Address, spender: Address) -> U256;
5458

5559
#[ink(message)]
56-
fn approve(&mut self, spender: Address, value: U256) -> bool;
60+
fn approve(&mut self, spender: Address, value: U256) -> Result<bool, Error>;
5761

5862
#[ink(message)]
5963
#[allow(non_snake_case)]
60-
fn transferFrom(&mut self, from: Address, to: Address, value: U256) -> bool;
64+
fn transferFrom(&mut self, from: Address, to: Address, value: U256) -> Result<bool, Error>;
65+
}
66+
67+
#[ink::event]
68+
#[cfg_attr(feature = "std", derive(Debug))]
69+
pub struct Created {
70+
pub id: AssetId,
6171
}
6272

6373
#[ink(storage)]
@@ -68,7 +78,9 @@ pub mod asset_hub_precompile {
6878
impl AssetHubPrecompile {
6979
#[ink(constructor, payable)]
7080
pub fn create(asset_id: AssetId) -> Self {
71-
Self { asset_id }
81+
let contract = Self { asset_id };
82+
contract.env().emit_event(Created { id: asset_id });
83+
contract
7284
}
7385

7486
#[ink(message)]
@@ -86,14 +98,14 @@ pub mod asset_hub_precompile {
8698
}
8799

88100
#[ink(message)]
89-
pub fn transfer(&mut self, to: Address, amount: U256) -> bool {
101+
pub fn transfer(&mut self, to: Address, amount: U256) -> Result<bool, Error> {
90102
let precompile_address = prefixed_address(PRECOMPILE_INDEX, self.asset_id);
91103
let mut precompile: contract_ref!(Erc20, DefaultEnvironment, Sol) = precompile_address.into();
92104
precompile.transfer(to, amount)
93105
}
94106

95107
#[ink(message)]
96-
pub fn approve(&mut self, spender: Address, amount: U256) -> bool {
108+
pub fn approve(&mut self, spender: Address, amount: U256) -> Result<bool, Error> {
97109
let precompile_address = prefixed_address(PRECOMPILE_INDEX, self.asset_id);
98110
let mut precompile: contract_ref!(Erc20, DefaultEnvironment, Sol) = precompile_address.into();
99111
precompile.approve(spender, amount)
@@ -107,11 +119,17 @@ pub mod asset_hub_precompile {
107119
}
108120

109121
#[ink(message)]
110-
pub fn transferFrom(&mut self, from: Address, to: Address, amount: U256) -> bool {
122+
pub fn transferFrom(&mut self, from: Address, to: Address, amount: U256) -> Result<bool, Error> {
111123
let precompile_address = prefixed_address(PRECOMPILE_INDEX, self.asset_id);
112124
let mut precompile: contract_ref!(Erc20, DefaultEnvironment, Sol) = precompile_address.into();
113125
precompile.transferFrom(from, to, amount)
114126
}
127+
128+
#[ink(message)]
129+
pub fn assetId(&self) -> AssetId {
130+
self.asset_id
131+
// 42
132+
}
115133
}
116134
}
117135

integration-tests/interfaces/IERC20.sol

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ interface IERC20 {
2727
*/
2828
function totalSupply() external view returns (uint256);
2929

30+
/**
31+
* @dev Returns the value of tokens in existence.
32+
*/
33+
function assetId() external view returns (uint32);
34+
3035
/**
3136
* @dev Returns the value of tokens owned by `account`.
3237
*/

integration-tests/src/assets.rs

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
use frame_support::traits::fungible::Inspect as _;
12
use frame_support::{
23
assert_noop,
3-
pallet_prelude::Encode,
4+
pallet_prelude::{Decode, Encode},
45
traits::fungibles::{
56
approvals::Inspect as _, metadata::Inspect as _, roles::Inspect as _, Inspect as _,
67
},
78
};
9+
use pallet_revive::precompiles::alloy::alloy_sol_types::SolValue;
810
use sp_io::hashing::twox_256;
911

1012
use super::*;
@@ -17,18 +19,42 @@ pallet_revive::precompiles::alloy::sol!(
1719
"interfaces/IERC20.sol"
1820
);
1921

22+
#[cfg_attr(feature = "std", derive(Debug, Encode))]
23+
pub struct Created {
24+
pub id: AssetId,
25+
}
26+
27+
#[test]
28+
fn asset_id_works() {
29+
let token = 42;
30+
let endowment = 100 * UNIT;
31+
ExtBuilder::new()
32+
.with_assets(vec![(token, ALICE, false, 1)])
33+
.with_asset_balances(vec![(token, BOB, endowment)])
34+
.build()
35+
.execute_with(|| {
36+
let contract = Contract::new(&BOB, 0, token);
37+
38+
// Test that asset_id returns the correct token ID
39+
assert_eq!(contract.asset_id(), token);
40+
});
41+
}
42+
2043
#[test]
2144
fn total_supply_works() {
22-
let token = 1;
23-
let endowment = 100;
45+
let token = 2;
46+
let endowment = 100 * UNIT;
2447
ExtBuilder::new()
2548
.with_assets(vec![(token, ALICE, false, 1)])
2649
.with_asset_balances(vec![(token, BOB, endowment)])
2750
.build()
2851
.execute_with(|| {
2952
let contract = Contract::new(&BOB, 0, token);
3053

54+
assert!(Assets::asset_exists(token));
55+
3156
// Tokens in circulation.
57+
assert_eq!(total_supply_precompile(token), Assets::total_supply(token).into());
3258
assert_eq!(contract.total_supply(), Assets::total_supply(token).into());
3359
assert_eq!(contract.total_supply(), endowment.into());
3460

@@ -45,8 +71,56 @@ struct Contract {
4571
creator: AccountId,
4672
}
4773

74+
/// Calculates the address of a precompile at index `n` and with some additional prefix.
75+
#[inline]
76+
pub fn fixed_address(n: u16) -> H160 {
77+
let shifted = (n as u32) << 16;
78+
79+
let suffix = shifted.to_be_bytes();
80+
let mut address = [0u8; 20];
81+
let mut i = 16;
82+
while i < address.len() {
83+
address[i] = suffix[i - 16];
84+
i = i + 1;
85+
}
86+
H160::from(address)
87+
}
88+
89+
/// Calculates the address of a precompile at index `n` and with some additional prefix.
90+
#[inline]
91+
pub fn prefixed_address(n: u16, prefix: u32) -> H160 {
92+
let address = fixed_address(n);
93+
let mut address_bytes: [u8; 20] = address.into();
94+
address_bytes[..4].copy_from_slice(&prefix.to_be_bytes());
95+
H160::from(address_bytes)
96+
}
97+
98+
fn total_supply_precompile(token: AssetId) -> U256 {
99+
let call = totalSupplyCall {};
100+
U256::from_little_endian(call_precompile(&BOB, call, 0, token).as_le_slice())
101+
}
102+
103+
fn call_precompile<T: SolCall>(
104+
origin: &AccountId,
105+
call: T,
106+
value: Balance,
107+
token: AssetId,
108+
) -> T::Return {
109+
let origin = RuntimeOrigin::signed(origin.clone());
110+
let dest = prefixed_address(0x0120, token);
111+
// let dest = self.address.clone();
112+
let data = call.abi_encode();
113+
let result = bare_call(origin, dest, value, GAS_LIMIT, STORAGE_DEPOSIT_LIMIT, data)
114+
.expect("should work");
115+
116+
match result.did_revert() {
117+
true => panic!("Contract call reverted: {:?}", String::from_utf8_lossy(&result.data)),
118+
false => T::abi_decode_returns(&result.data).expect("unable to decode success value"),
119+
}
120+
}
121+
48122
impl Contract {
49-
// Create a new instance of the contract through on-chain instantiation.
123+
// Create a new instance of the contract through on-chain instantiation (ink! style).
50124
fn new(origin: &AccountId, value: Balance, token: AssetId) -> Self {
51125
let data = [blake_selector("create").to_vec(), token.encode()].concat();
52126
let salt = twox_256(&value.to_le_bytes());
@@ -61,6 +135,14 @@ impl Contract {
61135
U256::from_little_endian(self.call(&self.creator, call, 0).as_le_slice())
62136
}
63137

138+
fn asset_id(&self) -> AssetId {
139+
let call = assetIdCall {};
140+
let data = self.call(&self.creator, call, 0);
141+
// let bytes: [u8; 4] = data.as_slice().try_into().expect("Expected 4 bytes for u32");
142+
// let result = u32::from_le_bytes(bytes);
143+
AssetId::from(data)
144+
}
145+
64146
fn account_id(&self) -> AccountId {
65147
to_account_id(&self.address)
66148
}

integration-tests/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::path::Path;
44

55
use frame_support::{assert_ok, weights::Weight};
66
use ink_parachain_runtime::{
7-
AccountId, Assets, Balance, Revive, Runtime, RuntimeOrigin, System, UNIT,
7+
AccountId, Assets, Balance, Balances, Revive, Runtime, RuntimeOrigin, System, UNIT,
88
};
99
use pallet_assets::{Instance1, NextAssetId};
1010
use pallet_revive::{

0 commit comments

Comments
 (0)