Skip to content
This repository has been archived by the owner on Oct 2, 2023. It is now read-only.

Commit

Permalink
Feature/precompile erc 721 token uri (#110)
Browse files Browse the repository at this point in the history
* create mock and testing

* first test

* testing ethereum reserved addresses

* refactoring

* refactoring

* refactoring tests

* fmt

* erc721 starting point

* fmt

* compiling

* check selectors

* create trait Erc721

* Erc721Precompile

* set mocks

* first implermentation

* first integration of erc721 in the runtime

* fmt

* check on the collection id

* test on extract owner form asset_id

* fix tests

* test for erc721 trait

* fix compilation

* refactoring

* returning address

* return value is correctly encoded as a n Address

* is_erc721_contract is not member of PrecompoileSet

* test on precompiled contracts

* erc721 returns hardcoded address

* refactoring

* testing return of asset ownership

* fix errors

* remove unused use

* create collection got an uri

* refactoring

* rewriting testing mod

* refactoring

* moving check for cllection address in pallet

* collection address prefix changed

* test passing

* test passing

* refactoring tests

* do not panic the runtime

* fmt

* solidity tokenId -> _tokenId

* erc721 functions are views

* update docs

* sp-core in std , removed duplicate function

* documentaetion

* using compilator type ifer

* compiler infer the size of the array

* added to std feature

* rename variable

* trait documentation

* using pallet errors

* Erc721Error created

* Erc721Error fix compilation

* tests green

* revise docuemntation

* fmt

* better name of constant

* create collection has param uri

* remove unused error

* using sp-std

* using sp-std

* created CollectionBaseURI

* created CollectionBaseURI

* BaseURILimit is defined

* insering the base uri

* insering the base uri

* base_uri is set in storage

* create_collection trait has base_uri as param

* living_assets_ownership pallet tests are green

* tests passing

* test on base_uri too long

* removing use

* use Vec

* testing minimum arguments

* create_collection has a BondedVec tokenURI

* removed unued error

* fix compilation

* refactoring

* refactoring

* removed legacy doc

* BaseURILimit type is not public

* traits have Error assiciated tyope

* more generiuc signature

* fix compilation

* test moved where concreate impl is tested

* removed harcoded buffer from tests

* refactoring

* checking for BaseURI bounds

* CollectionManager has associated type AssetId

* removed errors per trait (#128)

* removed errors per trait

* removed unused error variant

* added doc for error

* trait has BaseURI associated type

* fix compoilation

* BaseURILimit is int pallet::Config trait

* fix compoilation

* documentation for the value of BaseURILimit

* Base_URI is couled to trai Config

* usi max length to 2015
  • Loading branch information
asiniscalchi authored Aug 18, 2023
1 parent a14007c commit 6c43432
Show file tree
Hide file tree
Showing 13 changed files with 359 additions and 256 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions pallets/living-assets-ownership/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ frame-support = { workspace = true }
frame-system = { workspace = true }
sp-arithmetic = { workspace = true }
sp-core = { workspace = true }
sp-std = { workspace = true }

[dev-dependencies]
serde = { workspace = true }
Expand All @@ -47,6 +48,7 @@ std = [
"frame-system/std",
"sp-arithmetic/std",
"sp-core/std",
"sp-std/std",
]
try-runtime = [
"frame-system/try-runtime",
Expand Down
9 changes: 5 additions & 4 deletions pallets/living-assets-ownership/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ use sp_core::{H160, U256};

impl<T: Config> Pallet<T> {
/// See [Self::create_collection]
pub fn do_create_collection(who: T::AccountId) -> Result<CollectionId, Error<T>> {
pub fn do_create_collection(
who: T::AccountId,
base_uri: BaseURI<T>,
) -> Result<CollectionId, Error<T>> {
// Retrieve the current collection count to use as the new collection's ID
let collection_id = Self::collection_counter();

// Insert a new entry into the OwnerOfCollection map, mapping the new
// collection's ID to the owner's account ID
OwnerOfCollection::<T>::insert(collection_id, &who);
CollectionBaseURI::<T>::insert(collection_id, base_uri);

// Attempt to increment the collection counter by 1. If this operation
// would result in an overflow, return early with an error
Expand Down
83 changes: 54 additions & 29 deletions pallets/living-assets-ownership/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,19 @@ pub mod pallet {
use crate::functions::convert_asset_id_to_owner;

use super::*;
use frame_support::pallet_prelude::{OptionQuery, ValueQuery, *};
use frame_support::{
pallet_prelude::{OptionQuery, ValueQuery, *},
BoundedVec,
};
use frame_system::pallet_prelude::*;
use sp_core::{H160, U256};

/// Collection id type
/// TODO: use 256 bits
pub type CollectionId = u64;

/// Base URI type
pub type BaseURI<T> = BoundedVec<u8, <T as Config>::BaseURILimit>;

#[pallet::pallet]
pub struct Pallet<T>(_);

Expand All @@ -30,19 +35,30 @@ pub mod pallet {
pub trait Config: frame_system::Config {
/// Because this pallet emits events, it depends on the runtime's definition of an event.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
}

/// Mapping from collection id to owner
#[pallet::storage]
#[pallet::getter(fn owner_of_collection)]
pub(super) type OwnerOfCollection<T: Config> =
StorageMap<_, Blake2_128Concat, CollectionId, T::AccountId, OptionQuery>;
/// Specifies the advised maximum length for a Base URI.
//s
/// The URI standard (RFC 3986) doesn't dictates a limit for the length of URIs.
/// However it seems the max supported length in browsers is 2,048 characters.
///
/// The base should be capped at 2,015 characters in length. This ensures room for
/// the token URI formation, where it combines `BaseURILimit`, a `'/'`, and a `tokenID`
/// (which takes up 33 characters).
#[pallet::constant]
type BaseURILimit: Get<u32>;
}

/// Collection counter
#[pallet::storage]
#[pallet::getter(fn collection_counter)]
pub(super) type CollectionCounter<T: Config> = StorageValue<_, CollectionId, ValueQuery>;

/// Collection base URI
#[pallet::storage]
#[pallet::getter(fn collection_base_uri)]
pub(super) type CollectionBaseURI<T: Config> =
StorageMap<_, Blake2_128Concat, CollectionId, BaseURI<T>, OptionQuery>;

/// Pallet events
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
Expand All @@ -54,9 +70,22 @@ pub mod pallet {

// Errors inform users that something went wrong.
#[pallet::error]
#[derive(PartialEq)]
pub enum Error<T> {
/// Collection id overflow
CollectionIdOverflow,
/// Unexistent collection
UnexistentCollection,
}

impl<T: Config> AsRef<[u8]> for Error<T> {
fn as_ref(&self) -> &[u8] {
match self {
Error::__Ignore(_, _) => b"__Ignore",
Error::CollectionIdOverflow => b"CollectionIdOverflow",
Error::UnexistentCollection => b"UnexistentCollection",
}
}
}

// Dispatchable functions allows users to interact with the pallet and invoke state changes.
Expand All @@ -66,44 +95,40 @@ pub mod pallet {
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
#[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())] // TODO set proper weight
pub fn create_collection(origin: OriginFor<T>) -> DispatchResult {
pub fn create_collection(origin: OriginFor<T>, base_uri: BaseURI<T>) -> DispatchResult {
let who = ensure_signed(origin)?;

match Self::do_create_collection(who) {
match Self::do_create_collection(who, base_uri) {
Ok(_) => Ok(()),
Err(err) => Err(err.into()),
}
}
}

impl<T: Config> traits::CollectionManager<T::AccountId> for Pallet<T> {
fn owner_of_collection(collection_id: CollectionId) -> Option<T::AccountId> {
OwnerOfCollection::<T>::get(collection_id)
impl<T: Config> traits::CollectionManager for Pallet<T> {
type Error = Error<T>;
type AccountId = T::AccountId;
type BaseURI = BaseURI<T>;

fn base_uri(collection_id: CollectionId) -> Option<Self::BaseURI> {
CollectionBaseURI::<T>::get(collection_id)
}

fn create_collection(
owner: T::AccountId,
) -> Result<CollectionId, traits::CollectionManagerError> {
match Self::do_create_collection(owner) {
Ok(collection_id) => Ok(collection_id),
Err(err) => match err {
Error::CollectionIdOverflow => {
Err(traits::CollectionManagerError::CollectionIdOverflow)
},
_ => Err(traits::CollectionManagerError::UnknownError),
},
}
base_uri: Self::BaseURI,
) -> Result<CollectionId, Self::Error> {
Self::do_create_collection(owner, base_uri)
}
}

impl<T: Config> traits::Erc721 for Pallet<T> {
fn owner_of(
collection_id: CollectionId,
asset_id: U256,
) -> Result<H160, traits::Erc721Error> {
match OwnerOfCollection::<T>::get(collection_id) {
type Error = Error<T>;

fn owner_of(collection_id: CollectionId, asset_id: U256) -> Result<H160, Self::Error> {
match CollectionBaseURI::<T>::get(collection_id) {
Some(_) => Ok(convert_asset_id_to_owner(asset_id)),
None => Err(traits::Erc721Error::UnexistentCollection),
None => Err(Error::UnexistentCollection),
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion pallets/living-assets-ownership/src/mock.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate as pallet_livingassets_ownership;
use frame_support::traits::{ConstU16, ConstU64};
use sp_core::H256;
use sp_core::{ConstU32, H256};
use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup},
BuildStorage,
Expand Down Expand Up @@ -46,6 +46,7 @@ impl frame_system::Config for Test {

impl pallet_livingassets_ownership::Config for Test {
type RuntimeEvent = RuntimeEvent;
type BaseURILimit = ConstU32<256>;
}

// Build genesis storage according to the mock runtime.
Expand Down
Loading

0 comments on commit 6c43432

Please sign in to comment.