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/migrate nft ownership #921

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
49b1745
Update NFT pallet with TokenOwnership struct
JasonTulp Jan 22, 2025
79ae33e
Add test for zero issuance mints, fix xls-20 pallet
JasonTulp Jan 22, 2025
cbb9b31
Fix nft-peg benchmarks
JasonTulp Jan 22, 2025
b935dd5
Add MB Migration for NFT ownership
JasonTulp Jan 27, 2025
b5c3dce
Add tests and add ensure_migrated checks throughout codebase
JasonTulp Jan 30, 2025
7c340f3
Merge remote-tracking branch 'origin/main' into fix/migrate-nft-owner…
JasonTulp Jan 30, 2025
2ed6f07
cargo fmt --all
zees-dev Feb 12, 2025
10c7c80
Merge remote-tracking branch 'origin/main' into fix/migrate-nft-owner…
JasonTulp Feb 20, 2025
df0fa15
Fix broken tests
JasonTulp Feb 20, 2025
2782f1e
Fix build error
JasonTulp Feb 20, 2025
fe9e17f
Updates to migration pallet
JasonTulp Feb 20, 2025
5799211
fmt
JasonTulp Feb 24, 2025
d1b86f8
Update benchmarks for pallet-nft on fix/migrate-nft-ownership
actions-user Feb 25, 2025
b6c266a
Merge branch 'main' into fix/migrate-nft-ownership
JasonTulp Feb 26, 2025
29740b4
Merge remote-tracking branch 'origin/main' into fix/migrate-nft-owner…
JasonTulp Feb 26, 2025
2f53c1d
Add ensure_migrated to soulbound extrinsics and update to new token s…
JasonTulp Feb 26, 2025
c55608c
remove sort and add proper mint benchmark
JasonTulp Feb 27, 2025
7baf5d1
fix benchmark
JasonTulp Feb 27, 2025
906a36c
Update benchmarks for pallet-nft on fix/migrate-nft-ownership
actions-user Feb 27, 2025
d3cf208
Refactor token ownership, fix tests
JasonTulp Mar 3, 2025
d23a25b
Fix other pallets and tests
JasonTulp Mar 4, 2025
cb42bb4
Fix benchmarks
JasonTulp Mar 4, 2025
3aca64d
Optimise Migration, add tests + benchmarks
JasonTulp Mar 5, 2025
d6f0c22
Add verify for all NFT benchmarks
JasonTulp Mar 5, 2025
9f963f0
Update soulbound map in NFT pallet
JasonTulp Mar 5, 2025
0634f3a
Update soulbound map in SFT pallet to StorageNMap
JasonTulp Mar 5, 2025
d5c0086
Fix precompiles for soulbound
JasonTulp Mar 5, 2025
15415b7
Add migration for soulbound tokens
JasonTulp Mar 5, 2025
502e826
Fix NFT migration version check
JasonTulp Mar 5, 2025
d3d58da
Merge remote-tracking branch 'origin/main' into fix/migrate-nft-owner…
JasonTulp Mar 5, 2025
3a37e95
Update benchmarks for pallet-migration on fix/migrate-nft-ownership
actions-user Mar 5, 2025
c49560d
Iterate safely over iter_prefix
JasonTulp Mar 6, 2025
d4775a9
Merge remote-tracking branch 'origin/fix/migrate-nft-ownership' into …
JasonTulp Mar 6, 2025
f1e11ba
cargo fmt
JasonTulp Mar 6, 2025
ea00302
Update benchmarks for pallet-nft on fix/migrate-nft-ownership
actions-user Mar 6, 2025
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: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 19 additions & 20 deletions evm-precompiles/erc1155/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ use precompile_utils::{
prelude::*,
};
use seed_pallet_common::utils::TokenBurnAuthority;
use seed_primitives::{AssetId, Balance, CollectionUuid, MetadataScheme, SerialNumber, TokenId};
use seed_primitives::{
AssetId, Balance, CollectionUuid, IssuanceId, MetadataScheme, SerialNumber, TokenId,
};
use sp_core::{Encode, H160, H256, U256};
use sp_runtime::{traits::SaturatedConversion, BoundedVec};
use sp_std::{marker::PhantomData, vec, vec::Vec};
Expand Down Expand Up @@ -1290,8 +1292,7 @@ where
.map_err(|_| revert("ERC1155: Too many serial numbers in one issuance"))?;

handle.record_cost(RuntimeHelper::<Runtime>::db_read_gas_cost())?;
let next_issuance_id =
pallet_sft::PendingIssuances::<Runtime>::get(collection_id).next_issuance_id;
let next_issuance_id = pallet_sft::NextIssuanceId::<Runtime>::get();

// Dispatch call (if enough gas).
RuntimeHelper::<Runtime>::try_dispatch(
Expand Down Expand Up @@ -1325,18 +1326,15 @@ where

let owner: H160 = owner.into();

handle.record_cost(RuntimeHelper::<Runtime>::db_read_gas_cost())?;
let pending_issuances = pallet_sft::PendingIssuances::<Runtime>::get(collection_id)
.get_pending_issuances(&owner.into());

let issuance_ids = pending_issuances.iter().map(|p| U256::from(p.issuance_id)).collect();
let (issuance_ids, issuances): (Vec<U256>, Vec<Vec<(u32, u128)>>) = pallet_sft::PendingIssuances::<Runtime>::iter_prefix((
collection_id,
Runtime::AccountId::from(owner),
)).map(|(p, q)| (U256::from(p), q.into_inner())).collect();

let issuances: Vec<(Vec<SerialNumber>, Vec<Balance>, Vec<u8>)> = pending_issuances
.iter()
let issuances: Vec<(Vec<SerialNumber>, Vec<Balance>, Vec<u8>)> = issuances.into_iter()
.map(|p| -> EvmResult<(Vec<SerialNumber>, Vec<Balance>, Vec<u8>)> {
let (serial_numbers, balances): (Vec<SerialNumber>, Vec<Balance>) =
p.serial_numbers.clone().into_iter().unzip();

p.clone().into_iter().unzip();
let mut burn_auths = vec![];
for serial_number in serial_numbers.iter() {
handle.record_cost(RuntimeHelper::<Runtime>::db_read_gas_cost())?;
Expand Down Expand Up @@ -1371,10 +1369,10 @@ where

read_args!(handle, { issuance_id: U256 });

if issuance_id > u32::MAX.into() {
if issuance_id > IssuanceId::MAX.into() {
return Err(revert("ERC721: Expected issuance id <= 2^32"));
}
let issuance_id: u32 = issuance_id.saturated_into();
let issuance_id: IssuanceId = issuance_id.saturated_into();

let origin = handle.context().caller;

Expand All @@ -1387,11 +1385,12 @@ where
let collection_owner = collection.collection_owner;

handle.record_cost(RuntimeHelper::<Runtime>::db_read_gas_cost())?;
let pending_issuance = match pallet_sft::PendingIssuances::<Runtime>::get(collection_id)
.get_pending_issuance(&origin.into(), issuance_id)
{
Some(pending_issuance) => pending_issuance,
None => return Err(revert("Issuance does not exist")),
let Some(serial_numbers) = pallet_sft::PendingIssuances::<Runtime>::get((
collection_id,
&Runtime::AccountId::from(origin),
issuance_id,
)) else {
return Err(revert("Issuance does not exist"));
};

// Dispatch call (if enough gas).
Expand All @@ -1401,7 +1400,7 @@ where
pallet_sft::Call::<Runtime>::accept_soulbound_issuance { collection_id, issuance_id },
)?;

for (serial_number, _) in pending_issuance.serial_numbers {
for (serial_number, _) in serial_numbers {
handle.record_cost(RuntimeHelper::<Runtime>::db_read_gas_cost())?;
let burn_authority =
match pallet_sft::TokenUtilityFlags::<Runtime>::get((collection_id, serial_number))
Expand Down
56 changes: 27 additions & 29 deletions evm-precompiles/erc721/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use precompile_utils::{
};
use seed_pallet_common::{utils::TokenBurnAuthority, NFTExt};
use seed_primitives::{
AssetId, Balance, CollectionUuid, EthAddress, SerialNumber, TokenCount, TokenId,
AssetId, Balance, CollectionUuid, EthAddress, IssuanceId, SerialNumber, TokenCount, TokenId,
};
use sp_core::{Encode, H160, H256, U256};
use sp_runtime::{traits::SaturatedConversion, BoundedVec};
Expand Down Expand Up @@ -1215,8 +1215,7 @@ where
let origin = handle.context().caller;

handle.record_cost(RuntimeHelper::<Runtime>::db_read_gas_cost())?;
let next_issuance_id =
pallet_nft::PendingIssuances::<Runtime>::get(collection_id).next_issuance_id;
let next_issuance_id = pallet_nft::NextIssuanceId::<Runtime>::get();

// Dispatch call (if enough gas).
RuntimeHelper::<Runtime>::try_dispatch(
Expand Down Expand Up @@ -1257,16 +1256,13 @@ where
let owner: H160 = owner.into();

handle.record_cost(RuntimeHelper::<Runtime>::db_read_gas_cost())?;
let pending_issuances = pallet_nft::PendingIssuances::<Runtime>::get(collection_id)
.get_pending_issuances(&owner.into());

let issuance_ids: Vec<U256> =
pending_issuances.iter().map(|p| U256::from(p.issuance_id)).collect();

let issuances: Vec<(U256, u8)> = pending_issuances
.iter()
.map(|p| (U256::from(p.quantity), p.burn_authority.into()))
.collect();
let (issuance_ids, issuances): (Vec<IssuanceId>, Vec<(U256, u8)>) =
pallet_nft::PendingIssuances::<Runtime>::iter_prefix((
collection_id,
Runtime::AccountId::from(owner),
))
.map(|(p, q)| (p, (U256::from(q.quantity), q.burn_authority.into())))
.unzip();

Ok(succeed(EvmDataWriter::new().write(issuance_ids).write(issuances).build()))
}
Expand All @@ -1279,10 +1275,10 @@ where

read_args!(handle, { issuance_id: U256 });

if issuance_id > u32::MAX.into() {
return Err(revert("ERC721: Expected issuance id <= 2^32"));
if issuance_id > IssuanceId::MAX.into() {
return Err(revert("ERC721: Expected issuance id <= 2^64"));
}
let issuance_id: u32 = issuance_id.saturated_into();
let issuance_id: IssuanceId = issuance_id.saturated_into();

let origin = handle.context().caller;

Expand All @@ -1296,11 +1292,12 @@ where
let serial_number = collection.next_serial_number;

handle.record_cost(RuntimeHelper::<Runtime>::db_read_gas_cost())?;
let pending_issuance = match pallet_nft::PendingIssuances::<Runtime>::get(collection_id)
.get_pending_issuance(&origin.into(), issuance_id)
{
Some(pending_issuance) => pending_issuance,
None => return Err(revert("Issuance does not exist")),
let Some(pending_issuance) = pallet_nft::PendingIssuances::<Runtime>::get((
collection_id,
Runtime::AccountId::from(origin),
issuance_id,
)) else {
return Err(revert("Issuance does not exist"));
};

// Dispatch call (if enough gas).
Expand Down Expand Up @@ -1338,16 +1335,17 @@ where
if token_id > u32::MAX.into() {
return Err(revert("ERC721: Expected token id <= 2^32"));
}
let token_id: SerialNumber = token_id.saturated_into();
let serial_number: SerialNumber = token_id.saturated_into();

handle.record_cost(RuntimeHelper::<Runtime>::db_read_gas_cost())?;
let burn_auth: u8 =
match pallet_nft::TokenUtilityFlags::<Runtime>::get((collection_id, token_id))
.burn_authority
{
Some(burn_authority) => burn_authority.into(),
_ => 0, // default to TokenOwner
};
let token_info = match pallet_nft::TokenInfo::<Runtime>::get(collection_id, serial_number) {
Some(token_info) => token_info,
None => return Err(revert("ERC721: Token does not exist")),
};
let burn_auth: u8 = match token_info.utility_flags.burn_authority {
Some(burn_authority) => burn_authority.into(),
_ => 0, // default to TokenOwner
};

Ok(succeed(EvmDataWriter::new().write(burn_auth).build()))
}
Expand Down
5 changes: 4 additions & 1 deletion pallet/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,9 @@ pub trait NFTExt {
/// Returns Some(token_owner) for a token if the owner exists
fn get_token_owner(token_id: &TokenId) -> Option<Self::AccountId>;

/// Returns whether the token exists
fn token_exists(token_id: &TokenId) -> bool;

/// Returns collection current issuance and max issuance
fn get_collection_issuance(
collection_id: CollectionUuid,
Expand Down Expand Up @@ -609,7 +612,7 @@ pub trait NFTExt {
) -> DispatchResult;

/// Remove a token lock without performing checks
fn remove_token_lock(token_id: TokenId);
fn remove_token_lock(token_id: TokenId) -> DispatchResult;

fn get_collection_owner(
collection_id: CollectionUuid,
Expand Down
1 change: 1 addition & 0 deletions pallet/common/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ macro_rules! impl_pallet_nft_config {
type StringLimit = StringLimit;
type NFIRequest = ();
type MaxPendingIssuances = MaxPendingIssuances;
type Migrator = ();
}
};
}
Expand Down
Loading