1234567891011121314151617use evm_coder::{solidity_interface, types::*, execution::{Result, Error}};18pub use pallet_evm::{PrecompileOutput, PrecompileResult, account::CrossAccountId};19use pallet_evm_coder_substrate::{dispatch_to_evm, SubstrateRecorder};20use sp_core::{H160, U256};21use sp_std::vec::Vec;22use up_data_structs::Property;2324use crate::{Pallet, CollectionHandle, Config, CollectionProperties};25262728pub trait CommonEvmHandler {29 const CODE: &'static [u8];3031 fn call(self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileResult>;32}3334#[solidity_interface(name = "Collection")]35impl<T: Config> CollectionHandle<T> {36 fn set_collection_property(&mut self, caller: caller, key: string, value: bytes) -> Result<()> {37 let caller = T::CrossAccountId::from_eth(caller);38 let key = <Vec<u8>>::from(key)39 .try_into()40 .map_err(|_| "key too large")?;41 let value = value.try_into().map_err(|_| "value too large")?;4243 <Pallet<T>>::set_collection_property(self, &caller, Property { key, value })44 .map_err(dispatch_to_evm::<T>)45 }4647 fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {48 let caller = T::CrossAccountId::from_eth(caller);49 let key = <Vec<u8>>::from(key)50 .try_into()51 .map_err(|_| "key too large")?;5253 <Pallet<T>>::delete_collection_property(self, &caller, key).map_err(dispatch_to_evm::<T>)54 }5556 57 fn collection_property(&self, key: string) -> Result<bytes> {58 let key = <Vec<u8>>::from(key)59 .try_into()60 .map_err(|_| "key too large")?;6162 let props = <CollectionProperties<T>>::get(self.id);63 let prop = props.get(&key).ok_or("key not found")?;6465 Ok(prop.to_vec())66 }6768 fn eth_set_sponsor(69 &mut self,70 caller: caller,71 sponsor: address,72 ) -> Result<void> {73 check_is_owner(caller, self)?;7475 let sponsor = T::CrossAccountId::from_eth(sponsor);76 self.set_sponsor(sponsor.as_sub().clone());77 save(self);78 Ok(())79 }8081 fn eth_confirm_sponsorship(&mut self, caller: caller) -> Result<void> {82 let caller = T::CrossAccountId::from_eth(caller);83 if !self.confirm_sponsorship(caller.as_sub()) {84 return Err(Error::Revert("Caller is not set as sponsor".into()));85 }86 save(self);87 Ok(())88 }8990 fn set_limits(91 &self,92 caller: caller,93 limits_json: string,94 ) -> Result<void> {95 96 9798 99 100 101 102 Ok(())103 }104105 fn contract_address(&self, _caller: caller) -> Result<address> {106 Ok(crate::eth::collection_id_to_address(self.id))107 }108}109110fn collection_from_address<T: Config>(111 collection_address: address,112 gas_limit: u64113) -> Result<CollectionHandle<T>> {114 let collection_id = crate::eth::map_eth_to_id(&collection_address)115 .ok_or(Error::Revert("Contract is not an unique collection".into()))?;116 let recorder = <SubstrateRecorder<T>>::new(gas_limit);117 let collection =118 CollectionHandle::new_with_recorder(collection_id, recorder)119 .ok_or(Error::Revert("Create collection handle error".into()))?;120 Ok(collection)121}122123fn check_is_owner<T: Config>(caller: caller, collection: &CollectionHandle<T>) -> Result<()> {124 let caller = T::CrossAccountId::from_eth(caller);125 collection126 .check_is_owner(&caller)127 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;128 Ok(())129}130131fn save<T: Config>(collection: &CollectionHandle<T>) {132 <crate::CollectionById<T>>::insert(collection.id, collection.collection.clone());133}