difftreelog
feat sponsor token property modifications
in: master
3 files changed
pallets/unique/src/lib.rsdiffbeforeafterboth--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -242,6 +242,7 @@
/// Collection id (controlled?2), token id (controlled?2)
#[deprecated]
pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
+ pub TokenPropertyBasket get(fn token_property_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
/// Approval sponsoring
pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
runtime/common/src/eth_sponsoring.rsdiffbeforeafterboth30use crate::sponsoring::*;30use crate::sponsoring::*;313132use pallet_nonfungible::erc::{32use pallet_nonfungible::erc::{33 UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721MintableCall, ERC721Call,33 UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721MintableCall, ERC721Call, TokenPropertiesCall,34};34};35use pallet_fungible::erc::{UniqueFungibleCall, ERC20Call};35use pallet_fungible::erc::{UniqueFungibleCall, ERC20Call};36use pallet_fungible::Config as FungibleConfig;36use pallet_fungible::Config as FungibleConfig;50 CollectionMode::NFT => {50 CollectionMode::NFT => {51 let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;51 let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;52 match call {52 match call {53 UniqueNFTCall::TokenProperties(54 TokenPropertiesCall::SetProperty { token_id, key, value, .. },55 ) => {56 let token_id: TokenId = token_id.try_into().ok()?;57 withdraw_set_token_property::<T>(58 &collection,59 &who,60 &token_id,61 key.len() + value.len(),62 ).map(|()| sponsor)63 }53 UniqueNFTCall::ERC721UniqueExtensions(64 UniqueNFTCall::ERC721UniqueExtensions(54 ERC721UniqueExtensionsCall::Transfer { token_id, .. },65 ERC721UniqueExtensionsCall::Transfer { token_id, .. },55 ) => {66 ) => {runtime/common/src/sponsoring.rsdiffbeforeafterboth--- a/runtime/common/src/sponsoring.rs
+++ b/runtime/common/src/sponsoring.rs
@@ -29,8 +29,8 @@
use pallet_evm::account::CrossAccountId;
use pallet_unique::{
Call as UniqueCall, Config as UniqueConfig, FungibleApproveBasket, RefungibleApproveBasket,
- NftApproveBasket, CreateItemBasket, ReFungibleTransferBasket, FungibleTransferBasket,
- NftTransferBasket,
+ NftApproveBasket, CreateItemBasket, ReFungibleTransferBasket,
+ FungibleTransferBasket, NftTransferBasket, TokenPropertyBasket,
};
use pallet_fungible::Config as FungibleConfig;
use pallet_nonfungible::Config as NonfungibleConfig;
@@ -39,6 +39,51 @@
pub trait Config: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig {}
impl<T> Config for T where T: UniqueConfig + FungibleConfig + NonfungibleConfig + RefungibleConfig {}
+// TODO: permission check?
+pub fn withdraw_set_token_property<T: Config>(
+ collection: &CollectionHandle<T>,
+ who: &T::CrossAccountId,
+ item_id: &TokenId,
+ data_size: usize,
+) -> Option<()> {
+ // preliminary sponsoring correctness check
+ match collection.mode {
+ CollectionMode::NFT => {
+ let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;
+ if !owner.conv_eq(who) {
+ return None;
+ }
+ }
+ CollectionMode::Fungible(_) => {
+ // Fungible tokens have no properties
+ return None;
+ }
+ CollectionMode::ReFungible => {
+ if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {
+ return None;
+ }
+ }
+ }
+
+ if data_size > collection.limits.sponsored_data_size() as usize {
+ return None;
+ }
+
+ let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
+ let limit = collection.limits.sponsored_data_rate_limit()?;
+
+ if let Some(last_tx_block) = TokenPropertyBasket::<T>::get(collection.id, item_id) {
+ let timeout = last_tx_block + limit.into();
+ if block_number < timeout {
+ return None;
+ }
+ }
+
+ <TokenPropertyBasket<T>>::insert(collection.id, item_id, block_number);
+
+ Some(())
+}
+
pub fn withdraw_transfer<T: Config>(
collection: &CollectionHandle<T>,
who: &T::CrossAccountId,
@@ -190,6 +235,22 @@
{
fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {
match IsSubType::<UniqueCall<T>>::is_sub_type(call)? {
+ UniqueCall::set_token_properties {
+ collection_id,
+ token_id,
+ properties,
+ ..
+ } => {
+ let (sponsor, collection) = load::<T>(*collection_id)?;
+ withdraw_set_token_property(
+ &collection,
+ &T::CrossAccountId::from_sub(who.clone()),
+ &token_id,
+ // No overflow may happen, as data larger than usize can't reach here
+ properties.iter().map(|p| p.key.len() + p.value.len()).sum()
+ )
+ .map(|()| sponsor)
+ }
UniqueCall::create_item {
collection_id,
data,