difftreelog
feat sponsor token property modifications
in: master
3 files changed
pallets/unique/src/lib.rsdiffbeforeafterboth242 /// Collection id (controlled?2), token id (controlled?2)242 /// Collection id (controlled?2), token id (controlled?2)243 #[deprecated]243 #[deprecated]244 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;244 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;245 pub TokenPropertyBasket get(fn token_property_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;245246246 /// Approval sponsoring247 /// Approval sponsoring247 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;248 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.rsdiffbeforeafterboth--- a/runtime/common/src/eth_sponsoring.rs
+++ b/runtime/common/src/eth_sponsoring.rs
@@ -30,7 +30,7 @@
use crate::sponsoring::*;
use pallet_nonfungible::erc::{
- UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721MintableCall, ERC721Call,
+ UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721MintableCall, ERC721Call, TokenPropertiesCall,
};
use pallet_fungible::erc::{UniqueFungibleCall, ERC20Call};
use pallet_fungible::Config as FungibleConfig;
@@ -50,6 +50,17 @@
CollectionMode::NFT => {
let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader).ok()??;
match call {
+ UniqueNFTCall::TokenProperties(
+ TokenPropertiesCall::SetProperty { token_id, key, value, .. },
+ ) => {
+ let token_id: TokenId = token_id.try_into().ok()?;
+ withdraw_set_token_property::<T>(
+ &collection,
+ &who,
+ &token_id,
+ key.len() + value.len(),
+ ).map(|()| sponsor)
+ }
UniqueNFTCall::ERC721UniqueExtensions(
ERC721UniqueExtensionsCall::Transfer { token_id, .. },
) => {
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,