git.delta.rocks / unique-network / refs/commits / 9c9035103c33

difftreelog

feat implement #[weight] macro for evm support

Yaroslav Bolyukin2021-11-05parent: #e4d3792.patch.diff
in: master

35 files changed

modifiedcrates/evm-coder-macros/src/lib.rsdiffbeforeafterboth
211pub fn solidity(_args: TokenStream, stream: TokenStream) -> TokenStream {211pub fn solidity(_args: TokenStream, stream: TokenStream) -> TokenStream {
212 stream212 stream
213}213}
214#[proc_macro_attribute]
215pub fn weight(_args: TokenStream, stream: TokenStream) -> TokenStream {
216 stream
217}
214218
215#[proc_macro_derive(ToLog, attributes(indexed))]219#[proc_macro_derive(ToLog, attributes(indexed))]
216pub fn to_log(value: TokenStream) -> TokenStream {220pub fn to_log(value: TokenStream) -> TokenStream {
modifiedcrates/evm-coder-macros/src/solidity_interface.rsdiffbeforeafterboth
30 })30 })
31 }31 }
3232
33 fn expand_call_def(&self) -> proc_macro2::TokenStream {33 fn expand_call_def(&self, gen_ref: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
34 let name = &self.name;34 let name = &self.name;
35 let pascal_call_name = &self.pascal_call_name;35 let pascal_call_name = &self.pascal_call_name;
36 quote! {36 quote! {
37 #name(#pascal_call_name)37 #name(#pascal_call_name #gen_ref)
38 }38 }
39 }39 }
4040
46 }46 }
4747
48 fn expand_supports_interface(&self) -> proc_macro2::TokenStream {48 fn expand_supports_interface(
49 &self,
50 generics: &proc_macro2::TokenStream,
51 ) -> proc_macro2::TokenStream {
49 let pascal_call_name = &self.pascal_call_name;52 let pascal_call_name = &self.pascal_call_name;
50 quote! {53 quote! {
51 #pascal_call_name::supports_interface(interface_id)54 <#pascal_call_name #generics>::supports_interface(interface_id)
52 }55 }
53 }56 }
57
58 fn expand_variant_weight(&self) -> proc_macro2::TokenStream {
59 let name = &self.name;
60 quote! {
61 Self::#name(call) => call.weight()
62 }
63 }
5464
55 fn expand_variant_call(&self) -> proc_macro2::TokenStream {65 fn expand_variant_call(
66 &self,
67 call_name: &proc_macro2::Ident,
68 generics: &proc_macro2::TokenStream,
69 ) -> proc_macro2::TokenStream {
56 let name = &self.name;70 let name = &self.name;
57 let pascal_call_name = &self.pascal_call_name;71 let pascal_call_name = &self.pascal_call_name;
58 quote! {72 quote! {
59 InternalCall::#name(call) => return <Self as ::evm_coder::Callable<#pascal_call_name>>::call(self, Msg {73 #call_name::#name(call) => return <Self as ::evm_coder::Callable<#pascal_call_name #generics>>::call(self, Msg {
60 call,74 call,
61 caller: c.caller,75 caller: c.caller,
62 value: c.value,76 value: c.value,
63 })77 })
64 }78 }
65 }79 }
6680
67 fn expand_parse(&self) -> proc_macro2::TokenStream {81 fn expand_parse(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
68 let name = &self.name;82 let name = &self.name;
69 let pascal_call_name = &self.pascal_call_name;83 let pascal_call_name = &self.pascal_call_name;
70 quote! {84 quote! {
71 if let Some(parsed_call) = #pascal_call_name::parse(method_id, reader)? {85 if let Some(parsed_call) = <#pascal_call_name #generics>::parse(method_id, reader)? {
72 return Ok(Some(Self::#name(parsed_call)))86 return Ok(Some(Self::#name(parsed_call)))
73 }87 }
74 }88 }
75 }89 }
7690
77 fn expand_generator(&self) -> proc_macro2::TokenStream {91 fn expand_generator(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
78 let pascal_call_name = &self.pascal_call_name;92 let pascal_call_name = &self.pascal_call_name;
79 quote! {93 quote! {
80 #pascal_call_name::generate_solidity_interface(tc, is_impl);94 <#pascal_call_name #generics>::generate_solidity_interface(tc, is_impl);
81 }95 }
82 }96 }
8397
351 Pure,365 Pure,
352}366}
367
368pub struct WeightAttr(syn::Expr);
369
370mod keyword {
371 syn::custom_keyword!(weight);
372}
373
374impl syn::parse::Parse for WeightAttr {
375 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
376 input.parse::<syn::Token![#]>()?;
377 let content;
378 syn::bracketed!(content in input);
379 content.parse::<keyword::weight>()?;
380
381 let weight_content;
382 syn::parenthesized!(weight_content in content);
383 Ok(WeightAttr(weight_content.parse::<syn::Expr>()?))
384 }
385}
353386
354struct Method {387struct Method {
355 name: Ident,388 name: Ident,
362 has_normal_args: bool,395 has_normal_args: bool,
363 mutability: Mutability,396 mutability: Mutability,
364 result: Type,397 result: Type,
398 weight: Option<Expr>,
365 docs: Vec<String>,399 docs: Vec<String>,
366}400}
367impl Method {401impl Method {
370 rename_selector: None,404 rename_selector: None,
371 };405 };
372 let mut docs = Vec::new();406 let mut docs = Vec::new();
407 let mut weight = None;
373 for attr in &value.attrs {408 for attr in &value.attrs {
374 let ident = parse_ident_from_path(&attr.path, false)?;409 let ident = parse_ident_from_path(&attr.path, false)?;
375 if ident == "solidity" {410 if ident == "solidity" {
384 _ => unreachable!(),419 _ => unreachable!(),
385 };420 };
386 docs.push(value);421 docs.push(value);
387 }422 } else if ident == "weight" {
423 weight = Some(syn::parse2::<WeightAttr>(attr.to_token_stream())?.0);
424 }
388 }425 }
389 let ident = &value.sig.ident;426 let ident = &value.sig.ident;
390 let ident_str = ident.to_string();427 let ident_str = ident.to_string();
466 has_normal_args,503 has_normal_args,
467 mutability,504 mutability,
468 result: result.clone(),505 result: result.clone(),
506 weight,
469 docs,507 docs,
470 })508 })
471 }509 }
528 }566 }
529 }567 }
530568
531 fn expand_variant_call(&self) -> proc_macro2::TokenStream {569 fn expand_variant_call(&self, call_name: &proc_macro2::Ident) -> proc_macro2::TokenStream {
532 let pascal_name = &self.pascal_name;570 let pascal_name = &self.pascal_name;
533 let name = &self.name;571 let name = &self.name;
534572
555 let args = self.args.iter().map(|a| a.expand_call_arg());593 let args = self.args.iter().map(|a| a.expand_call_arg());
556594
557 quote! {595 quote! {
558 InternalCall::#pascal_name #matcher => {596 #call_name::#pascal_name #matcher => {
559 let result = #receiver #name(597 let result = #receiver #name(
560 #(598 #(
561 #args,599 #args,
562 )*600 )*
563 )?;601 )?;
564 (&result).abi_write(&mut writer);602 (&result).into_result()
565 }603 }
566 }604 }
567 }605 }
606
607 fn expand_variant_weight(&self) -> proc_macro2::TokenStream {
608 let pascal_name = &self.pascal_name;
609 if let Some(weight) = &self.weight {
610 let matcher = if self.has_normal_args {
611 let names = self
612 .args
613 .iter()
614 .filter(|a| !a.is_special())
615 .map(|a| &a.name);
616
617 quote! {{
618 #(
619 #names,
620 )*
621 }}
622 } else {
623 quote! {}
624 };
625 quote! {
626 Self::#pascal_name #matcher => (#weight).into()
627 }
628 } else {
629 let matcher = if self.has_normal_args {
630 quote! {{..}}
631 } else {
632 quote! {}
633 };
634 quote! {
635 Self::#pascal_name #matcher => ().into()
636 }
637 }
638 }
568639
569 fn expand_solidity_function(&self) -> proc_macro2::TokenStream {640 fn expand_solidity_function(&self) -> proc_macro2::TokenStream {
570 let camel_name = &self.camel_name;641 let camel_name = &self.camel_name;
600 }671 }
601}672}
673
674fn generics_list(gen: &Generics) -> proc_macro2::TokenStream {
675 if gen.params.is_empty() {
676 return quote! {};
677 }
678 let params = gen.params.iter().map(|p| match p {
679 syn::GenericParam::Type(id) => {
680 let v = &id.ident;
681 quote! {#v}
682 }
683 syn::GenericParam::Lifetime(lt) => {
684 let v = &lt.lifetime;
685 quote! {#v}
686 }
687 syn::GenericParam::Const(c) => {
688 let i = &c.ident;
689 quote! {#i}
690 }
691 });
692 quote! { #(#params),* }
693}
694fn generics_reference(gen: &Generics) -> proc_macro2::TokenStream {
695 if gen.params.is_empty() {
696 return quote! {};
697 }
698 let list = generics_list(gen);
699 quote! { <#list> }
700}
701fn generics_data(gen: &Generics) -> proc_macro2::TokenStream {
702 let list = generics_list(gen);
703 if gen.params.len() == 1 {
704 quote! {#list}
705 } else {
706 quote! { (#list) }
707 }
708}
602709
603pub struct SolidityInterface {710pub struct SolidityInterface {
604 generics: Generics,711 generics: Generics,
628 let solidity_name = self.info.name.to_string();735 let solidity_name = self.info.name.to_string();
629 let call_name = pascal_ident_to_call(&self.info.name);736 let call_name = pascal_ident_to_call(&self.info.name);
630 let generics = self.generics;737 let generics = self.generics;
738 let gen_ref = generics_reference(&generics);
739 let gen_data = generics_data(&generics);
631740
632 let call_sub = self741 let call_sub = self
633 .info742 .info
634 .inline_is743 .inline_is
635 .0744 .0
636 .iter()745 .iter()
637 .chain(self.info.is.0.iter())746 .chain(self.info.is.0.iter())
638 .map(Is::expand_call_def);747 .map(|c| Is::expand_call_def(c, &gen_ref));
639 let call_parse = self748 let call_parse = self
640 .info749 .info
641 .inline_is750 .inline_is
642 .0751 .0
643 .iter()752 .iter()
644 .chain(self.info.is.0.iter())753 .chain(self.info.is.0.iter())
645 .map(Is::expand_parse);754 .map(|is| Is::expand_parse(is, &gen_ref));
646 let call_variants = self755 let call_variants = self
647 .info756 .info
648 .inline_is757 .inline_is
649 .0758 .0
650 .iter()759 .iter()
651 .chain(self.info.is.0.iter())760 .chain(self.info.is.0.iter())
652 .map(Is::expand_variant_call);761 .map(|c| Is::expand_variant_call(c, &call_name, &gen_ref));
762 let weight_variants = self
763 .info
764 .inline_is
765 .0
766 .iter()
767 .chain(self.info.is.0.iter())
768 .map(Is::expand_variant_weight);
653769
654 let inline_interface_id = self.info.inline_is.0.iter().map(Is::expand_interface_id);770 let inline_interface_id = self.info.inline_is.0.iter().map(Is::expand_interface_id);
655 let supports_interface = self.info.is.0.iter().map(Is::expand_supports_interface);771 let supports_interface = self
772 .info
773 .is
774 .0
775 .iter()
776 .map(|is| Is::expand_supports_interface(is, &gen_ref));
656777
657 let calls = self.methods.iter().map(Method::expand_call_def);778 let calls = self.methods.iter().map(Method::expand_call_def);
658 let consts = self.methods.iter().map(Method::expand_const);779 let consts = self.methods.iter().map(Method::expand_const);
659 let interface_id = self.methods.iter().map(Method::expand_interface_id);780 let interface_id = self.methods.iter().map(Method::expand_interface_id);
660 let parsers = self.methods.iter().map(Method::expand_parse);781 let parsers = self.methods.iter().map(Method::expand_parse);
661 let call_variants_this = self.methods.iter().map(Method::expand_variant_call);782 let call_variants_this = self
783 .methods
784 .iter()
785 .map(|m| Method::expand_variant_call(m, &call_name));
786 let weight_variants_this = self.methods.iter().map(Method::expand_variant_weight);
662 let solidity_functions = self.methods.iter().map(Method::expand_solidity_function);787 let solidity_functions = self.methods.iter().map(Method::expand_solidity_function);
663788
664 // TODO: Inline inline_is789 // TODO: Inline inline_is
676 .0801 .0
677 .iter()802 .iter()
678 .chain(self.info.inline_is.0.iter())803 .chain(self.info.inline_is.0.iter())
679 .map(Is::expand_generator);804 .map(|is| Is::expand_generator(is, &gen_ref));
680 let solidity_event_generators = self.info.events.0.iter().map(Is::expand_event_generator);805 let solidity_event_generators = self.info.events.0.iter().map(Is::expand_event_generator);
681806
682 // let methods = self.methods.iter().map(Method::solidity_def);807 // let methods = self.methods.iter().map(Method::solidity_def);
683808
684 quote! {809 quote! {
685 #[derive(Debug)]810 #[derive(Debug)]
686 pub enum #call_name {811 pub enum #call_name #gen_ref {
687 ERC165Call(::evm_coder::ERC165Call),812 ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<#gen_data>),
688 #(813 #(
689 #calls,814 #calls,
690 )*815 )*
691 #(816 #(
692 #call_sub,817 #call_sub,
693 )*818 )*
694 }819 }
695 impl #call_name {820 impl #gen_ref #call_name #gen_ref {
696 #(821 #(
697 #consts822 #consts
698 )*823 )*
699 pub const fn interface_id() -> u32 {824 pub fn interface_id() -> u32 {
700 let mut interface_id = 0;825 let mut interface_id = 0;
701 #(#interface_id)*826 #(#interface_id)*
702 #(#inline_interface_id)*827 #(#inline_interface_id)*
748 tc.collect(out);873 tc.collect(out);
749 }874 }
750 }875 }
751 impl ::evm_coder::Call for #call_name {876 impl #gen_ref ::evm_coder::Call for #call_name #gen_ref {
752 fn parse(method_id: u32, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {877 fn parse(method_id: u32, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {
753 use ::evm_coder::abi::AbiRead;878 use ::evm_coder::abi::AbiRead;
754 match method_id {879 match method_id {
755 ::evm_coder::ERC165Call::INTERFACE_ID => return Ok(::evm_coder::ERC165Call::parse(method_id, reader)?.map(Self::ERC165Call)),880 ::evm_coder::ERC165Call::INTERFACE_ID => return Ok(
881 ::evm_coder::ERC165Call::parse(method_id, reader)?
882 .map(|c| Self::ERC165Call(c, ::core::marker::PhantomData))
883 ),
756 #(884 #(
757 #parsers,885 #parsers,
764 return Ok(None);892 return Ok(None);
765 }893 }
766 }894 }
767 impl #generics ::evm_coder::Callable<#call_name> for #name {895 impl #generics ::evm_coder::Weighted for #call_name #gen_ref {
896 #[allow(unused_variables)]
897 fn weight(&self) -> ::evm_coder::execution::DispatchInfo {
898 match self {
899 #(
900 #weight_variants,
901 )*
902 // TODO: It should be very cheap, but not free
903 Self::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {..}, _) => 100u64.into(),
904 #(
905 #weight_variants_this,
906 )*
907 }
908 }
909 }
910 impl #generics ::evm_coder::Callable<#call_name #gen_ref> for #name {
768 #[allow(unreachable_code)] // In case of no inner calls911 #[allow(unreachable_code)] // In case of no inner calls
769 fn call(&mut self, c: Msg<#call_name>) -> Result<::evm_coder::abi::AbiWriter> {912 fn call(&mut self, c: Msg<#call_name #gen_ref>) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {
770 use ::evm_coder::abi::AbiWrite;913 use ::evm_coder::abi::AbiWrite;
771 type InternalCall = #call_name;
772 match c.call {914 match c.call {
773 #(915 #(
774 #call_variants,916 #call_variants,
775 )*917 )*
776 InternalCall::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {interface_id}) => {918 #call_name::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {interface_id}, _) => {
777 let mut writer = ::evm_coder::abi::AbiWriter::default();919 let mut writer = ::evm_coder::abi::AbiWriter::default();
778 writer.bool(&InternalCall::supports_interface(interface_id));920 writer.bool(&<#call_name #gen_ref>::supports_interface(interface_id));
779 return Ok(writer);921 return Ok(writer.into());
780 }922 }
781 _ => {},923 _ => {},
782 }924 }
787 )*929 )*
788 _ => unreachable!()930 _ => unreachable!()
789 }931 }
790 Ok(writer)
791 }932 }
792 }933 }
793 }934 }
modifiedcrates/evm-coder/src/abi.rsdiffbeforeafterboth
12use primitive_types::{H160, U256};12use primitive_types::{H160, U256};
1313
14use crate::{execution::Error, types::string};14use crate::{
15 execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},
16 types::string,
17};
15use crate::execution::Result;18use crate::execution::Result;
1619
244}247}
245248
246impl_abi_readable!(u32, uint32);249impl_abi_readable!(u32, uint32);
250impl_abi_readable!(u64, uint64);
247impl_abi_readable!(u128, uint128);251impl_abi_readable!(u128, uint128);
248impl_abi_readable!(U256, uint256);252impl_abi_readable!(U256, uint256);
249impl_abi_readable!(H160, address);253impl_abi_readable!(H160, address);
306310
307pub trait AbiWrite {311pub trait AbiWrite {
308 fn abi_write(&self, writer: &mut AbiWriter);312 fn abi_write(&self, writer: &mut AbiWriter);
313 fn into_result(&self) -> ResultWithPostInfo<AbiWriter> {
314 let mut writer = AbiWriter::new();
315 self.abi_write(&mut writer);
316 Ok(writer.into())
317 }
309}318}
319
320impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {
321 // this particular AbiWrite implementation should be split to another trait,
322 // which only implements [`into_result`]
323 //
324 // But due to lack of specialization feature in stable Rust, we can't have
325 // blanket impl of this trait `for T where T: AbiWrite`, so here we abusing
326 // default trait methods for it
327 fn abi_write(&self, _writer: &mut AbiWriter) {
328 debug_assert!(false, "shouldn't be called, see comment")
329 }
330 fn into_result(&self) -> ResultWithPostInfo<AbiWriter> {
331 match self {
332 Ok(v) => Ok(WithPostDispatchInfo {
333 post_info: v.post_info.clone(),
334 data: {
335 let mut out = AbiWriter::new();
336 v.data.abi_write(&mut out);
337 out
338 },
339 }),
340 Err(e) => Err(e.clone()),
341 }
342 }
343}
310344
311macro_rules! impl_abi_writeable {345macro_rules! impl_abi_writeable {
312 ($ty:ty, $method:ident) => {346 ($ty:ty, $method:ident) => {
modifiedcrates/evm-coder/src/execution.rsdiffbeforeafterboth
4#[cfg(feature = "std")]4#[cfg(feature = "std")]
5use std::string::{String, ToString};5use std::string::{String, ToString};
6
7use crate::Weight;
68
7#[derive(Debug)]9#[derive(Debug, Clone)]
8pub enum Error {10pub enum Error {
9 Revert(String),11 Revert(String),
10 Fatal(ExitFatal),12 Fatal(ExitFatal),
2224
23pub type Result<T> = core::result::Result<T, Error>;25pub type Result<T> = core::result::Result<T, Error>;
26
27pub struct DispatchInfo {
28 pub weight: Weight,
29}
30
31impl From<Weight> for DispatchInfo {
32 fn from(weight: Weight) -> Self {
33 Self { weight }
34 }
35}
36impl From<()> for DispatchInfo {
37 fn from(_: ()) -> Self {
38 Self { weight: 0 }
39 }
40}
41
42#[derive(Default, Clone)]
43pub struct PostDispatchInfo {
44 actual_weight: Option<Weight>,
45}
46
47impl PostDispatchInfo {
48 pub fn calc_unspent(&self, info: &DispatchInfo) -> Weight {
49 info.weight - self.calc_actual_weight(info)
50 }
51
52 pub fn calc_actual_weight(&self, info: &DispatchInfo) -> Weight {
53 if let Some(actual_weight) = self.actual_weight {
54 actual_weight.min(info.weight)
55 } else {
56 info.weight
57 }
58 }
59}
60
61#[derive(Clone)]
62pub struct WithPostDispatchInfo<T> {
63 pub data: T,
64 pub post_info: PostDispatchInfo,
65}
66
67impl<T> From<T> for WithPostDispatchInfo<T> {
68 fn from(data: T) -> Self {
69 Self {
70 data,
71 post_info: Default::default(),
72 }
73 }
74}
75
76pub type ResultWithPostInfo<T> =
77 core::result::Result<WithPostDispatchInfo<T>, WithPostDispatchInfo<Error>>;
2478
modifiedcrates/evm-coder/src/lib.rsdiffbeforeafterboth
3extern crate alloc;3extern crate alloc;
44
5use abi::{AbiRead, AbiReader, AbiWriter};5use abi::{AbiRead, AbiReader, AbiWriter};
6pub use evm_coder_macros::{event_topic, fn_selector, solidity_interface, solidity, ToLog};6pub use evm_coder_macros::{event_topic, fn_selector, solidity_interface, solidity, weight, ToLog};
7pub mod abi;7pub mod abi;
8pub mod events;8pub mod events;
9pub use events::ToLog;9pub use events::ToLog;
10use execution::DispatchInfo;
10pub mod execution;11pub mod execution;
11pub mod solidity;12pub mod solidity;
1213
57 fn parse(selector: u32, input: &mut AbiReader) -> execution::Result<Option<Self>>;58 fn parse(selector: u32, input: &mut AbiReader) -> execution::Result<Option<Self>>;
58}59}
60
61pub type Weight = u64;
62
63pub trait Weighted: Call {
64 fn weight(&self) -> DispatchInfo;
65}
5966
60pub trait Callable<C: Call> {67pub trait Callable<C: Call> {
61 fn call(&mut self, call: types::Msg<C>) -> execution::Result<AbiWriter>;68 fn call(&mut self, call: types::Msg<C>) -> execution::ResultWithPostInfo<AbiWriter>;
62}69}
6370
64/// Implementation is implicitly provided for all interfaces71/// Implementation is implicitly provided for all interfaces
84 }91 }
85}92}
8693
94/// Generate "tests", which will generate solidity code on execution and print it to stdout
95/// Script at .maintain/scripts/generate_api.sh can split this output from test runtime
96///
97/// This macro receives type usage as second argument, but you can use anything as generics,
98/// because no bounds are implied
87#[macro_export]99#[macro_export]
88macro_rules! generate_stubgen {100macro_rules! generate_stubgen {
89 ($name:ident, $decl:ident, $is_impl:literal) => {101 ($name:ident, $decl:ty, $is_impl:literal) => {
90 #[test]102 #[test]
91 #[ignore]103 #[ignore]
92 fn $name() {104 fn $name() {
93 use evm_coder::solidity::TypeCollector;105 use evm_coder::solidity::TypeCollector;
94 let mut out = TypeCollector::new();106 let mut out = TypeCollector::new();
95 $decl::generate_solidity_interface(&mut out, $is_impl);107 <$decl>::generate_solidity_interface(&mut out, $is_impl);
96 println!("=== SNIP START ===");108 println!("=== SNIP START ===");
97 println!("// SPDX-License-Identifier: OTHER");109 println!("// SPDX-License-Identifier: OTHER");
98 println!("// This code is automatically generated");110 println!("// This code is automatically generated");
deletedcrates/evm-coder/tests/a.rsdiffbeforeafterboth

no changes

addedcrates/evm-coder/tests/generics.rsdiffbeforeafterboth

no changes

addedcrates/evm-coder/tests/log.rsdiffbeforeafterboth

no changes

addedcrates/evm-coder/tests/random.rsdiffbeforeafterboth

no changes

addedcrates/evm-coder/tests/solidity_generation.rsdiffbeforeafterboth

no changes

modifiednode/cli/Cargo.tomldiffbeforeafterboth
268jsonrpc-core = '18.0.0'268jsonrpc-core = '18.0.0'
269jsonrpc-pubsub = "18.0.0"269jsonrpc-pubsub = "18.0.0"
270270
271fc-rpc-core = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }271fc-rpc-core = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
272fc-consensus = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }272fc-consensus = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
273fc-mapping-sync = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }273fc-mapping-sync = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
274fc-rpc = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }274fc-rpc = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
275fc-db = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }275fc-db = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
276fp-rpc = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }276fp-rpc = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
277pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }277pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
278278
279nft-rpc = { path = "../rpc" }279nft-rpc = { path = "../rpc" }
280280
modifiednode/rpc/Cargo.tomldiffbeforeafterboth
41substrate-frame-rpc-system = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }41substrate-frame-rpc-system = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
42tokio = { version = "0.2.25", features = ["macros", "sync"] }42tokio = { version = "0.2.25", features = ["macros", "sync"] }
4343
44pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }44pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
45fc-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }45fc-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
46fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }46fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
47fc-rpc-core = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }47fc-rpc-core = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
48fc-db = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }48fc-db = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
49fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }49fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
5050
51pallet-nft = { path = "../../pallets/nft" }51pallet-nft = { path = "../../pallets/nft" }
52uc-rpc = { path = "../../client/rpc" }52uc-rpc = { path = "../../client/rpc" }
modifiedpallets/common/Cargo.tomldiffbeforeafterboth
19pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }19pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
20evm-coder = { default-features = false, path = '../../crates/evm-coder' }20evm-coder = { default-features = false, path = '../../crates/evm-coder' }
2121
22pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }22pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
23serde = { version = "1.0.130", default-features = false }23serde = { version = "1.0.130", default-features = false }
24scale-info = { version = "1.0.0", default-features = false, features = [24scale-info = { version = "1.0.0", default-features = false, features = [
25 "derive",25 "derive",
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
1#![cfg_attr(not(feature = "std"), no_std)]1#![cfg_attr(not(feature = "std"), no_std)]
22
3use core::ops::{Deref, DerefMut};3use core::ops::{Deref, DerefMut};
4use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
4use sp_std::vec::Vec;5use sp_std::vec::Vec;
5use account::CrossAccountId;6use account::CrossAccountId;
6use frame_support::{7use frame_support::{
7 dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo},8 dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo},
8 ensure, fail,9 ensure, fail,
9 traits::{Imbalance, Get, Currency},10 traits::{Imbalance, Get, Currency},
10};11};
12use pallet_evm::GasWeightMapping;
11use nft_data_structs::{13use nft_data_structs::{
12 COLLECTION_NUMBER_LIMIT, Collection, CollectionId, CreateItemData, ExistenceRequirement,14 COLLECTION_NUMBER_LIMIT, Collection, CollectionId, CreateItemData, ExistenceRequirement,
13 MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_COLLECTION_NAME_LENGTH, MAX_TOKEN_PREFIX_LENGTH,15 MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_COLLECTION_NAME_LENGTH, MAX_TOKEN_PREFIX_LENGTH,
27pub struct CollectionHandle<T: Config> {29pub struct CollectionHandle<T: Config> {
28 pub id: CollectionId,30 pub id: CollectionId,
29 collection: Collection<T>,31 collection: Collection<T>,
30 pub recorder: pallet_evm_coder_substrate::SubstrateRecorder<T>,32 pub recorder: SubstrateRecorder<T>,
31}33}
34impl<T: Config> WithRecorder<T> for CollectionHandle<T> {
35 fn recorder(&self) -> &SubstrateRecorder<T> {
36 &self.recorder
37 }
38 fn into_recorder(self) -> SubstrateRecorder<T> {
39 self.recorder
40 }
41}
32impl<T: Config> CollectionHandle<T> {42impl<T: Config> CollectionHandle<T> {
33 pub fn new_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {43 pub fn new_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {
34 <CollectionById<T>>::get(id).map(|collection| Self {44 <CollectionById<T>>::get(id).map(|collection| Self {
35 id,45 id,
36 collection,46 collection,
37 recorder: pallet_evm_coder_substrate::SubstrateRecorder::new(47 recorder: SubstrateRecorder::new(eth::collection_id_to_address(id), gas_limit),
38 eth::collection_id_to_address(id),
39 gas_limit,
40 ),
46 pub fn try_get(id: CollectionId) -> Result<Self, DispatchError> {53 pub fn try_get(id: CollectionId) -> Result<Self, DispatchError> {
47 Ok(Self::new(id).ok_or_else(|| <Error<T>>::CollectionNotFound)?)54 Ok(Self::new(id).ok_or_else(|| <Error<T>>::CollectionNotFound)?)
48 }55 }
49 pub fn log(&self, log: impl evm_coder::ToLog) -> DispatchResult {56 pub fn log(&self, log: impl evm_coder::ToLog) {
50 self.recorder.log_sub(log)57 self.recorder.log(log)
51 }58 }
52 pub fn log_infallible(&self, log: impl evm_coder::ToLog) {59 pub fn consume_store_reads(&self, reads: u64) -> evm_coder::execution::Result<()> {
53 self.recorder.log_infallible(log)
54 }
55 #[allow(dead_code)]
56 fn consume_gas(&self, gas: u64) -> DispatchResult {
57 self.recorder.consume_gas_sub(gas)
58 }
59 pub fn consume_sload(&self) -> DispatchResult {
60 self.recorder.consume_sload_sub()60 self.recorder
61 .consume_gas(T::GasWeightMapping::weight_to_gas(
62 <T as frame_system::Config>::DbWeight::get()
63 .read
64 .saturating_mul(reads),
65 ))
61 }66 }
62 pub fn consume_sstores(&self, amount: usize) -> DispatchResult {67 pub fn consume_store_writes(&self, writes: u64) -> evm_coder::execution::Result<()> {
63 self.recorder.consume_sstores_sub(amount)
64 }
65 pub fn consume_sstore(&self) -> DispatchResult {
66 self.recorder.consume_sstore_sub()
67 }
68 pub fn consume_log(&self, topics: usize, data: usize) -> DispatchResult {
69 self.recorder.consume_log_sub(topics, data)68 self.recorder
69 .consume_gas(T::GasWeightMapping::weight_to_gas(
70 <T as frame_system::Config>::DbWeight::get()
71 .write
72 .saturating_mul(writes),
73 ))
70 }74 }
71 pub fn submit_logs(self) -> DispatchResult {75 pub fn submit_logs(self) {
72 self.recorder.submit_logs()76 self.recorder.submit_logs()
73 }77 }
74 pub fn save(self) -> DispatchResult {78 pub fn save(self) -> DispatchResult {
75 self.recorder.submit_logs()?;79 self.recorder.submit_logs();
76 <CollectionById<T>>::insert(self.id, self.collection);80 <CollectionById<T>>::insert(self.id, self.collection);
77 Ok(())81 Ok(())
78 }82 }
96 ensure!(*subject.as_sub() == self.owner, <Error<T>>::NoPermission);100 ensure!(*subject.as_sub() == self.owner, <Error<T>>::NoPermission);
97 Ok(())101 Ok(())
98 }102 }
99 pub fn is_owner_or_admin(&self, subject: &T::CrossAccountId) -> Result<bool, DispatchError> {103 pub fn is_owner_or_admin(&self, subject: &T::CrossAccountId) -> bool {
100 self.consume_sload()?;
101
102 Ok(*subject.as_sub() == self.owner || <IsAdmin<T>>::get((self.id, subject)))104 *subject.as_sub() == self.owner || <IsAdmin<T>>::get((self.id, subject))
103 }105 }
104 pub fn check_is_owner_or_admin(&self, subject: &T::CrossAccountId) -> DispatchResult {106 pub fn check_is_owner_or_admin(&self, subject: &T::CrossAccountId) -> DispatchResult {
105 ensure!(self.is_owner_or_admin(subject)?, <Error<T>>::NoPermission);107 ensure!(self.is_owner_or_admin(subject), <Error<T>>::NoPermission);
106 Ok(())108 Ok(())
107 }109 }
108 pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> Result<bool, DispatchError> {110 pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> bool {
109 Ok(self.limits.owner_can_transfer() && self.is_owner_or_admin(user)?)111 self.limits.owner_can_transfer() && self.is_owner_or_admin(user)
110 }112 }
111 pub fn ignores_owned_amount(&self, user: &T::CrossAccountId) -> Result<bool, DispatchError> {113 pub fn ignores_owned_amount(&self, user: &T::CrossAccountId) -> bool {
112 Ok(self.limits.owner_can_transfer() && self.is_owner_or_admin(user)?)114 self.limits.owner_can_transfer() && self.is_owner_or_admin(user)
113 }115 }
114 pub fn check_allowlist(&self, user: &T::CrossAccountId) -> DispatchResult {116 pub fn check_allowlist(&self, user: &T::CrossAccountId) -> DispatchResult {
115 self.consume_sload()?;
116
117 ensure!(117 ensure!(
118 <Allowlist<T>>::get((self.id, user)),118 <Allowlist<T>>::get((self.id, user)),
modifiedpallets/evm-coder-substrate/Cargo.tomldiffbeforeafterboth
9sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }11sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
10ethereum = { version = "0.9", git = "https://github.com/purestake/ethereum", branch = "joshy-scale-info", default-features = false }12ethereum = { version = "0.9", git = "https://github.com/purestake/ethereum", branch = "joshy-scale-info", default-features = false }
11evm-coder = { default-features = false, path = "../../crates/evm-coder" }13evm-coder = { default-features = false, path = "../../crates/evm-coder" }
12pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }14pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
13pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }15pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
14frame-support = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }16frame-support = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
15frame-system = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }17frame-system = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
18frame-benchmarking = { default-features = false, optional = true, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
1619
17[dependencies.codec]20[dependencies.codec]
18default-features = false21default-features = false
31 "pallet-evm/std",34 "pallet-evm/std",
32 "frame-support/std",35 "frame-support/std",
33 "frame-system/std",36 "frame-system/std",
37 'frame-benchmarking/std',
34]38]
39runtime-benchmarks = ['frame-benchmarking']
3540
addedpallets/evm-coder-substrate/src/benchmarking.rsdiffbeforeafterboth

no changes

modifiedpallets/evm-coder-substrate/src/lib.rsdiffbeforeafterboth
22
3#[cfg(not(feature = "std"))]3#[cfg(not(feature = "std"))]
4extern crate alloc;4extern crate alloc;
5// #[cfg(feature = "runtime-benchmarks")]
6// pub mod benchmarking;
57
6pub use pallet::*;8pub use pallet::*;
79
18 };20 };
19 use frame_support::{ensure};21 use frame_support::{ensure};
20 use pallet_evm::{ExitError, ExitReason, ExitRevert, ExitSucceed, PrecompileOutput};22 use pallet_evm::{
23 ExitError, ExitReason, ExitRevert, ExitSucceed, PrecompileOutput, GasWeightMapping,
24 };
25 use frame_system::ensure_signed;
21 pub use frame_support::dispatch::DispatchResult;26 pub use frame_support::dispatch::DispatchResult;
22 use pallet_ethereum::EthereumTransactionSender;27 use pallet_ethereum::EthereumTransactionSender;
23 use sp_std::cell::RefCell;28 use sp_std::cell::RefCell;
24 use sp_std::vec::Vec;29 use sp_std::vec::Vec;
25 use sp_core::{H160, H256};30 use sp_core::{H160, H256};
26 use ethereum::Log;31 use ethereum::Log;
27 use frame_support::{pallet_prelude::*, traits::PalletInfo};32 use frame_support::{pallet_prelude::*, traits::PalletInfo};
33 use frame_system::pallet_prelude::*;
2834
29 /// DispatchError is opaque, but we need to somehow extract correct error in case of OutOfGas failure35 /// DispatchError is opaque, but we need to somehow extract correct error in case of OutOfGas failure
30 /// So we have this pallet, which defines OutOfGas error, and knews its own id to check if DispatchError36 /// So we have this pallet, which defines OutOfGas error, and knews its own id to check if DispatchError
40 #[pallet::config]46 #[pallet::config]
41 pub trait Config: frame_system::Config {47 pub trait Config: frame_system::Config {
42 type EthereumTransactionSender: pallet_ethereum::EthereumTransactionSender;48 type EthereumTransactionSender: pallet_ethereum::EthereumTransactionSender;
49 type GasWeightMapping: pallet_evm::GasWeightMapping;
43 }50 }
4451
45 #[pallet::pallet]52 #[pallet::pallet]
46 pub struct Pallet<T>(_);53 pub struct Pallet<T>(_);
4754
48 // FIXME: those items are defined as private in evm_gasometer::consts, and we can't directly use it55 #[pallet::call]
49 pub const G_LOG: u64 = 375;
50 pub const G_LOGDATA: u64 = 8;56 impl<T: Config> Pallet<T> {
57 #[pallet::weight(0)]
51 pub const G_LOGTOPIC: u64 = 375;58 pub fn empty_call(origin: OriginFor<T>) -> DispatchResult {
59 let _sender = ensure_signed(origin)?;
60 Ok(())
61 }
62 }
5263
53 // From instabul hardfork configuration: https://github.com/rust-blockchain/evm/blob/fd4fd6acc0ca3208d6770fdb3ba407c94cdf97c6/runtime/src/lib.rs#L28464 // From instabul hardfork configuration: https://github.com/rust-blockchain/evm/blob/fd4fd6acc0ca3208d6770fdb3ba407c94cdf97c6/runtime/src/lib.rs#L284
54 pub const G_SLOAD_WORD: u64 = 800;65 pub const G_SLOAD_WORD: u64 = 800;
55 pub const G_SSTORE_WORD: u64 = 20000;66 pub const G_SSTORE_WORD: u64 = 20000;
56
57 fn log_price(data: usize, topics: usize) -> u64 {
58 G_LOG
59 .saturating_add((data as u64).saturating_mul(G_LOGDATA))
60 .saturating_add((topics as u64).saturating_mul(G_LOGTOPIC))
61 }
6267
63 pub fn generate_transaction() -> ethereum::TransactionV0 {68 pub fn generate_transaction() -> ethereum::TransactionV0 {
64 use ethereum::{TransactionV0, TransactionAction, TransactionSignature};69 use ethereum::{TransactionV0, TransactionAction, TransactionSignature};
98 pub fn is_empty(&self) -> bool {103 pub fn is_empty(&self) -> bool {
99 self.logs.borrow().is_empty()104 self.logs.borrow().is_empty()
100 }105 }
101 pub fn log_sub(&self, log: impl ToLog) -> DispatchResult {106 // TODO: Replace with real storage in pallet-ethereum,
102 self.log_raw_sub(log.to_log(self.contract))107 // same way as it is done with frame_system's Events
103 }
104 pub fn log_raw_sub(&self, log: Log) -> DispatchResult {
105 self.consume_gas_sub(log_price(log.data.len(), log.topics.len()))?;
106 self.logs.borrow_mut().push(log);
107 Ok(())
108 }
109 /// Doesn't consumes any gas, should be used after consume_log_sub108 /// Doesn't consumes any gas, should be used after consume_log_sub
110 pub fn log_infallible(&self, log: impl ToLog) {109 pub fn log(&self, log: impl ToLog) {
111 self.logs.borrow_mut().push(log.to_log(self.contract));110 self.logs.borrow_mut().push(log.to_log(self.contract));
112 }111 }
113 pub fn retrieve_logs(self) -> Vec<Log> {112 pub fn retrieve_logs(self) -> Vec<Log> {
126 pub fn consume_sstore_sub(&self) -> DispatchResult {125 pub fn consume_sstore_sub(&self) -> DispatchResult {
127 self.consume_gas_sub(G_SSTORE_WORD)126 self.consume_gas_sub(G_SSTORE_WORD)
128 }127 }
129 pub fn consume_log_sub(&self, topics: usize, data: usize) -> DispatchResult {
130 self.consume_gas_sub(log_price(data, topics))
131 }
132 pub fn consume_gas_sub(&self, gas: u64) -> DispatchResult {128 pub fn consume_gas_sub(&self, gas: u64) -> DispatchResult {
133 ensure!(gas != u64::MAX, Error::<T>::OutOfGas);129 ensure!(gas != u64::MAX, Error::<T>::OutOfGas);
134 let mut gas_limit = self.gas_limit.borrow_mut();130 let mut gas_limit = self.gas_limit.borrow_mut();
154 *gas_limit -= gas;150 *gas_limit -= gas;
155 Ok(())151 Ok(())
156 }152 }
153 pub fn return_gas(&self, gas: u64) {
154 let mut gas_limit = self.gas_limit.borrow_mut();
155 *gas_limit += gas;
156 }
157157
158 pub fn evm_to_precompile_output(158 pub fn evm_to_precompile_output(
159 self,159 self,
181 })181 })
182 }182 }
183183
184 pub fn submit_logs(self) -> DispatchResult {184 pub fn submit_logs(self) {
185 let logs = self.retrieve_logs();185 let logs = self.retrieve_logs();
186 if logs.is_empty() {186 if logs.is_empty() {
187 return Ok(());187 return;
188 }188 }
189 T::EthereumTransactionSender::submit_logs_transaction(generate_transaction(), logs)189 T::EthereumTransactionSender::submit_logs_transaction(
190 Default::default(),
191 generate_transaction(),
192 logs,
193 )
190 }194 }
191 }195 }
215 }219 }
216 }220 }
217221
218 pub fn call_internal<C: evm_coder::Call, E: evm_coder::Callable<C>>(222 pub trait WithRecorder<T: Config> {
223 fn recorder(&self) -> &SubstrateRecorder<T>;
224 fn into_recorder(self) -> SubstrateRecorder<T>;
225 }
226
227 /// Helper to simplify implementing bridge between evm-coder definitions and pallet-evm
228 pub fn call<
229 T: Config,
230 C: evm_coder::Call + evm_coder::Weighted,
231 E: evm_coder::Callable<C> + WithRecorder<T>,
232 >(
233 caller: H160,
234 mut e: E,
235 value: value,
236 input: &[u8],
237 ) -> Option<PrecompileOutput> {
238 let result = call_internal(caller, &mut e, value, input);
239 e.into_recorder().evm_to_precompile_output(result)
240 }
241
242 fn call_internal<
243 T: Config,
244 C: evm_coder::Call + evm_coder::Weighted,
245 E: evm_coder::Callable<C> + WithRecorder<T>,
246 >(
219 caller: H160,247 caller: H160,
220 e: &mut E,248 e: &mut E,
228 }256 }
229 let call = call.unwrap();257 let call = call.unwrap();
258
259 let dispatch_info = call.weight();
260 e.recorder()
261 .consume_gas(T::GasWeightMapping::weight_to_gas(dispatch_info.weight))?;
262
230 e.call(Msg {263 match e.call(Msg {
231 call,264 call,
232 caller,265 caller,
233 value,266 value,
234 })267 }) {
268 Ok(v) => {
269 let unspent = v.post_info.calc_unspent(&dispatch_info);
270 e.recorder()
235 .map(Some)271 .return_gas(T::GasWeightMapping::weight_to_gas(unspent));
272 Ok(Some(v.data))
273 }
274 Err(v) => {
275 let unspent = v.post_info.calc_unspent(&dispatch_info);
276 e.recorder()
277 .return_gas(T::GasWeightMapping::weight_to_gas(unspent));
278 Err(v.data)
279 }
280 }
236 }281 }
237}282}
238283
modifiedpallets/evm-contract-helpers/Cargo.tomldiffbeforeafterboth
12sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }14sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
13evm-coder = { default-features = false, path = '../../crates/evm-coder' }15evm-coder = { default-features = false, path = '../../crates/evm-coder' }
14pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }16pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
15pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }17pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
16up-sponsorship = { default-features = false, path = '../../primitives/sponsorship' }18up-sponsorship = { default-features = false, path = '../../primitives/sponsorship' }
17log = "0.4.14"19log = "0.4.14"
1820
addedpallets/evm-contract-helpers/exp.rsdiffbeforeafterboth

no changes

modifiedpallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth
1use core::marker::PhantomData;1use core::marker::PhantomData;
2use evm_coder::{abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*};2use evm_coder::{abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*};
3use pallet_evm_coder_substrate::SubstrateRecorder;3use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
4use pallet_evm::{ExitReason, ExitRevert, OnCreate, OnMethodCall, PrecompileOutput};4use pallet_evm::{ExitReason, ExitRevert, OnCreate, OnMethodCall, PrecompileOutput};
5use sp_core::H160;5use sp_core::H160;
6use crate::{6use crate::{
11use sp_std::{convert::TryInto, vec::Vec};11use sp_std::{convert::TryInto, vec::Vec};
1212
13struct ContractHelpers<T: Config>(SubstrateRecorder<T>);13struct ContractHelpers<T: Config>(SubstrateRecorder<T>);
14impl<T: Config> WithRecorder<T> for ContractHelpers<T> {
15 fn recorder(&self) -> &SubstrateRecorder<T> {
16 &self.0
17 }
18
19 fn into_recorder(self) -> SubstrateRecorder<T> {
20 self.0
21 }
22}
1423
15#[solidity_interface(name = "ContractHelpers")]24#[solidity_interface(name = "ContractHelpers")]
16impl<T: Config> ContractHelpers<T> {25impl<T: Config> ContractHelpers<T> {
17 fn contract_owner(&self, contract_address: address) -> Result<address> {26 fn contract_owner(&self, contract_address: address) -> Result<address> {
18 self.0.consume_sload()?;
19 Ok(<Owner<T>>::get(contract_address))27 Ok(<Owner<T>>::get(contract_address))
20 }28 }
2129
22 fn sponsoring_enabled(&self, contract_address: address) -> Result<bool> {30 fn sponsoring_enabled(&self, contract_address: address) -> Result<bool> {
23 self.0.consume_sload()?;
24 Ok(<SelfSponsoring<T>>::get(contract_address))31 Ok(<SelfSponsoring<T>>::get(contract_address))
25 }32 }
2633
30 contract_address: address,37 contract_address: address,
31 enabled: bool,38 enabled: bool,
32 ) -> Result<void> {39 ) -> Result<void> {
33 self.0.consume_sload()?;
34 <Pallet<T>>::ensure_owner(contract_address, caller)?;40 <Pallet<T>>::ensure_owner(contract_address, caller)?;
35 self.0.consume_sstore()?;
36 <Pallet<T>>::toggle_sponsoring(contract_address, enabled);41 <Pallet<T>>::toggle_sponsoring(contract_address, enabled);
37 Ok(())42 Ok(())
38 }43 }
43 contract_address: address,48 contract_address: address,
44 rate_limit: uint32,49 rate_limit: uint32,
45 ) -> Result<void> {50 ) -> Result<void> {
46 self.0.consume_sload()?;
47 <Pallet<T>>::ensure_owner(contract_address, caller)?;51 <Pallet<T>>::ensure_owner(contract_address, caller)?;
48 self.0.consume_sstore()?;
49 <Pallet<T>>::set_sponsoring_rate_limit(contract_address, rate_limit.into());52 <Pallet<T>>::set_sponsoring_rate_limit(contract_address, rate_limit.into());
50 Ok(())53 Ok(())
51 }54 }
5255
53 fn get_sponsoring_rate_limit(&self, contract_address: address) -> Result<uint32> {56 fn get_sponsoring_rate_limit(&self, contract_address: address) -> Result<uint32> {
54 self.0.consume_sload()?;
55 Ok(<SponsoringRateLimit<T>>::get(contract_address)57 Ok(<SponsoringRateLimit<T>>::get(contract_address)
56 .try_into()58 .try_into()
57 .map_err(|_| "rate limit > u32::MAX")?)59 .map_err(|_| "rate limit > u32::MAX")?)
58 }60 }
5961
60 fn allowed(&self, contract_address: address, user: address) -> Result<bool> {62 fn allowed(&self, contract_address: address, user: address) -> Result<bool> {
61 self.0.consume_sload()?;
62 Ok(<Pallet<T>>::allowed(contract_address, user, true))63 Ok(<Pallet<T>>::allowed(contract_address, user, true))
63 }64 }
6465
65 fn allowlist_enabled(&self, contract_address: address) -> Result<bool> {66 fn allowlist_enabled(&self, contract_address: address) -> Result<bool> {
66 self.0.consume_sload()?;
67 Ok(<AllowlistEnabled<T>>::get(contract_address))67 Ok(<AllowlistEnabled<T>>::get(contract_address))
68 }68 }
6969
73 contract_address: address,73 contract_address: address,
74 enabled: bool,74 enabled: bool,
75 ) -> Result<void> {75 ) -> Result<void> {
76 self.0.consume_sload()?;
77 <Pallet<T>>::ensure_owner(contract_address, caller)?;76 <Pallet<T>>::ensure_owner(contract_address, caller)?;
78 self.0.consume_sstore()?;
79 <Pallet<T>>::toggle_allowlist(contract_address, enabled);77 <Pallet<T>>::toggle_allowlist(contract_address, enabled);
80 Ok(())78 Ok(())
81 }79 }
87 user: address,85 user: address,
88 allowed: bool,86 allowed: bool,
89 ) -> Result<void> {87 ) -> Result<void> {
90 self.0.consume_sload()?;
91 <Pallet<T>>::ensure_owner(contract_address, caller)?;88 <Pallet<T>>::ensure_owner(contract_address, caller)?;
92 self.0.consume_sstore()?;
93 <Pallet<T>>::toggle_allowed(contract_address, user, allowed);89 <Pallet<T>>::toggle_allowed(contract_address, user, allowed);
94 Ok(())90 Ok(())
95 }91 }
130 return None;126 return None;
131 }127 }
132128
133 let mut helpers = ContractHelpers::<T>(SubstrateRecorder::<T>::new(*target, gas_left));129 let helpers = ContractHelpers::<T>(SubstrateRecorder::<T>::new(*target, gas_left));
134 let result = pallet_evm_coder_substrate::call_internal(*source, &mut helpers, value, input);130 pallet_evm_coder_substrate::call(*source, helpers, value, input)
135 helpers.0.evm_to_precompile_output(result)
136 }131 }
137132
138 fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {133 fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {
170 }165 }
171}166}
172167
173generate_stubgen!(contract_helpers_impl, ContractHelpersCall, true);168generate_stubgen!(contract_helpers_impl, ContractHelpersCall<()>, true);
174generate_stubgen!(contract_helpers_iface, ContractHelpersCall, false);169generate_stubgen!(contract_helpers_iface, ContractHelpersCall<()>, false);
175170
modifiedpallets/evm-contract-helpers/src/stubs/ContractHelpers.soldiffbeforeafterboth
21 }21 }
22}22}
2323
24// Selector: 31acb1fe
24contract ContractHelpers is Dummy, ERC165 {25contract ContractHelpers is Dummy, ERC165 {
25 // Selector: contractOwner(address) 5152b14c26 // Selector: contractOwner(address) 5152b14c
26 function contractOwner(address contractAddress)27 function contractOwner(address contractAddress)
modifiedpallets/evm-migration/Cargo.tomldiffbeforeafterboth
12sp-std = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }14sp-std = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
13sp-io = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }15sp-io = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
14sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }16sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
15pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }17pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
16fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }18fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
1719
18[dependencies.codec]20[dependencies.codec]
19default-features = false21default-features = false
modifiedpallets/evm-transaction-payment/Cargo.tomldiffbeforeafterboth
11sp-std = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }13sp-std = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
12sp-io = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }14sp-io = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
13sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }15sp-core = { default-features = false, git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.12' }
14pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }16pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
15fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }17fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
16pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }18pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
17up-sponsorship = { default-features = false, path = '../../primitives/sponsorship' }19up-sponsorship = { default-features = false, path = '../../primitives/sponsorship' }
1820
19[dependencies.codec]21[dependencies.codec]
modifiedpallets/fungible/src/erc.rsdiffbeforeafterboth
1use core::char::{REPLACEMENT_CHARACTER, decode_utf16};1use core::char::{REPLACEMENT_CHARACTER, decode_utf16};
2use core::convert::TryInto;2use core::convert::TryInto;
3use evm_coder::{ToLog, execution::*, generate_stubgen, solidity_interface, types::*};3use evm_coder::{ToLog, execution::*, generate_stubgen, solidity_interface, types::*, weight};
4use nft_data_structs::CollectionMode;4use nft_data_structs::CollectionMode;
5use pallet_common::erc::CommonEvmHandler;5use pallet_common::erc::CommonEvmHandler;
6use sp_core::{H160, U256};6use sp_core::{H160, U256};
7use sp_std::vec::Vec;7use sp_std::vec::Vec;
8use pallet_common::account::CrossAccountId;8use pallet_common::account::CrossAccountId;
9use pallet_common::erc::PrecompileOutput;9use pallet_common::erc::PrecompileOutput;
10use pallet_evm_coder_substrate::{call_internal, dispatch_to_evm};10use pallet_evm_coder_substrate::{call, dispatch_to_evm};
1111
12use crate::{Allowance, Balance, Config, FungibleHandle, Pallet, TotalSupply};12use crate::{
13 Allowance, Balance, Config, FungibleHandle, Pallet, SelfWeightOf, TotalSupply,
14 weights::WeightInfo,
15};
1316
14#[derive(ToLog)]17#[derive(ToLog)]
40 Ok(string::from_utf8_lossy(&self.token_prefix).into())43 Ok(string::from_utf8_lossy(&self.token_prefix).into())
41 }44 }
42 fn total_supply(&self) -> Result<uint256> {45 fn total_supply(&self) -> Result<uint256> {
46 self.consume_store_reads(1)?;
43 Ok(<TotalSupply<T>>::get(self.id).into())47 Ok(<TotalSupply<T>>::get(self.id).into())
44 }48 }
4549
51 })55 })
52 }56 }
53 fn balance_of(&self, owner: address) -> Result<uint256> {57 fn balance_of(&self, owner: address) -> Result<uint256> {
58 self.consume_store_reads(1)?;
54 let owner = T::CrossAccountId::from_eth(owner);59 let owner = T::CrossAccountId::from_eth(owner);
55 let balance = <Balance<T>>::get((self.id, owner));60 let balance = <Balance<T>>::get((self.id, owner));
56 Ok(balance.into())61 Ok(balance.into())
57 }62 }
63 #[weight(<SelfWeightOf<T>>::transfer())]
58 fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {64 fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {
59 let caller = T::CrossAccountId::from_eth(caller);65 let caller = T::CrossAccountId::from_eth(caller);
60 let to = T::CrossAccountId::from_eth(to);66 let to = T::CrossAccountId::from_eth(to);
63 <Pallet<T>>::transfer(self, &caller, &to, amount).map_err(|_| "transfer error")?;69 <Pallet<T>>::transfer(self, &caller, &to, amount).map_err(|_| "transfer error")?;
64 Ok(true)70 Ok(true)
65 }71 }
72 #[weight(<SelfWeightOf<T>>::transfer_from())]
66 fn transfer_from(73 fn transfer_from(
67 &mut self,74 &mut self,
68 caller: caller,75 caller: caller,
79 .map_err(dispatch_to_evm::<T>)?;86 .map_err(dispatch_to_evm::<T>)?;
80 Ok(true)87 Ok(true)
81 }88 }
89 #[weight(<SelfWeightOf<T>>::approve())]
82 fn approve(&mut self, caller: caller, spender: address, amount: uint256) -> Result<bool> {90 fn approve(&mut self, caller: caller, spender: address, amount: uint256) -> Result<bool> {
83 let caller = T::CrossAccountId::from_eth(caller);91 let caller = T::CrossAccountId::from_eth(caller);
84 let spender = T::CrossAccountId::from_eth(spender);92 let spender = T::CrossAccountId::from_eth(spender);
89 Ok(true)97 Ok(true)
90 }98 }
91 fn allowance(&self, owner: address, spender: address) -> Result<uint256> {99 fn allowance(&self, owner: address, spender: address) -> Result<uint256> {
100 self.consume_store_reads(1)?;
92 let owner = T::CrossAccountId::from_eth(owner);101 let owner = T::CrossAccountId::from_eth(owner);
93 let spender = T::CrossAccountId::from_eth(spender);102 let spender = T::CrossAccountId::from_eth(spender);
94103
98107
99#[solidity_interface(name = "ERC20UniqueExtensions")]108#[solidity_interface(name = "ERC20UniqueExtensions")]
100impl<T: Config> FungibleHandle<T> {109impl<T: Config> FungibleHandle<T> {
110 #[weight(<SelfWeightOf<T>>::burn_from())]
101 fn burn_from(&mut self, caller: caller, from: address, amount: uint256) -> Result<bool> {111 fn burn_from(&mut self, caller: caller, from: address, amount: uint256) -> Result<bool> {
102 let caller = T::CrossAccountId::from_eth(caller);112 let caller = T::CrossAccountId::from_eth(caller);
103 let from = T::CrossAccountId::from_eth(from);113 let from = T::CrossAccountId::from_eth(from);
111#[solidity_interface(name = "UniqueFungible", is(ERC20))]121#[solidity_interface(name = "UniqueFungible", is(ERC20))]
112impl<T: Config> FungibleHandle<T> {}122impl<T: Config> FungibleHandle<T> {}
113123
114generate_stubgen!(gen_impl, UniqueFungibleCall, true);124generate_stubgen!(gen_impl, UniqueFungibleCall<()>, true);
115generate_stubgen!(gen_iface, UniqueFungibleCall, false);125generate_stubgen!(gen_iface, UniqueFungibleCall<()>, false);
116126
117impl<T: Config> CommonEvmHandler for FungibleHandle<T> {127impl<T: Config> CommonEvmHandler for FungibleHandle<T> {
118 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");128 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");
119129
120 fn call(mut self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileOutput> {130 fn call(self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileOutput> {
121 let result = call_internal::<UniqueFungibleCall, _>(*source, &mut self, value, input);131 call::<T, UniqueFungibleCall<T>, _>(*source, self, value, input)
122 self.0.recorder.evm_to_precompile_output(result)
123 }132 }
124}133}
125134
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
6use pallet_common::{6use pallet_common::{
7 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, account::CrossAccountId,7 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, account::CrossAccountId,
8};8};
9use pallet_evm_coder_substrate::WithRecorder;
9use sp_core::H160;10use sp_core::H160;
10use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};11use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};
11use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};12use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
82 self.083 self.0
83 }84 }
84}85}
86impl<T: Config> WithRecorder<T> for FungibleHandle<T> {
87 fn recorder(&self) -> &pallet_evm_coder_substrate::SubstrateRecorder<T> {
88 self.0.recorder()
89 }
90 fn into_recorder(self) -> pallet_evm_coder_substrate::SubstrateRecorder<T> {
91 self.0.into_recorder()
92 }
93}
85impl<T: Config> Deref for FungibleHandle<T> {94impl<T: Config> Deref for FungibleHandle<T> {
86 type Target = pallet_common::CollectionHandle<T>;95 type Target = pallet_common::CollectionHandle<T>;
8796
136 }145 }
137 <TotalSupply<T>>::insert(collection.id, total_supply);146 <TotalSupply<T>>::insert(collection.id, total_supply);
138147
139 collection.log_infallible(ERC20Events::Transfer {148 collection.log(ERC20Events::Transfer {
140 from: *owner.as_eth(),149 from: *owner.as_eth(),
141 to: H160::default(),150 to: H160::default(),
142 value: amount.into(),151 value: amount.into(),
180 None189 None
181 };190 };
182
183 collection.consume_sstore()?;
184 collection.consume_sstore()?;
185 collection.consume_log(2, 32)?;
186 collection.consume_sstore()?;
187191
188 // =========192 // =========
189193
197 <Balance<T>>::insert((collection.id, to), balance_to);201 <Balance<T>>::insert((collection.id, to), balance_to);
198 }202 }
199203
200 collection.log_infallible(ERC20Events::Transfer {204 collection.log(ERC20Events::Transfer {
201 from: *from.as_eth(),205 from: *from.as_eth(),
202 to: *to.as_eth(),206 to: *to.as_eth(),
203 value: amount.into(),207 value: amount.into(),
217 sender: &T::CrossAccountId,221 sender: &T::CrossAccountId,
218 data: Vec<CreateItemData<T>>,222 data: Vec<CreateItemData<T>>,
219 ) -> DispatchResult {223 ) -> DispatchResult {
220 let unrestricted_minting = collection.is_owner_or_admin(sender)?;224 if !collection.is_owner_or_admin(sender) {
221 if !unrestricted_minting {
222 ensure!(225 ensure!(
223 collection.mint_mode,226 collection.mint_mode,
224 <CommonError<T>>::PublicMintingNotAllowed227 <CommonError<T>>::PublicMintingNotAllowed
241 .ok_or(ArithmeticError::Overflow)?;244 .ok_or(ArithmeticError::Overflow)?;
242245
243 for (user, amount) in data.into_iter() {246 for (user, amount) in data.into_iter() {
244 collection.consume_sload()?;
245 let balance = balances247 let balance = balances
246 .entry(user.clone())248 .entry(user.clone())
247 .or_insert_with(|| <Balance<T>>::get((collection.id, user)));249 .or_insert_with(|| <Balance<T>>::get((collection.id, user)));
250 .ok_or(ArithmeticError::Overflow)?;252 .ok_or(ArithmeticError::Overflow)?;
251 }253 }
252
253 collection.consume_sstore()?;
254 for _ in &balances {
255 collection.consume_sstore()?;
256 collection.consume_log(2, 32)?;
257 collection.consume_sstore()?;
258 }
259254
260 // =========255 // =========
261256
262 <TotalSupply<T>>::insert(collection.id, total_supply);257 <TotalSupply<T>>::insert(collection.id, total_supply);
263 for (user, amount) in balances {258 for (user, amount) in balances {
264 <Balance<T>>::insert((collection.id, &user), amount);259 <Balance<T>>::insert((collection.id, &user), amount);
265260
266 collection.log_infallible(ERC20Events::Transfer {261 collection.log(ERC20Events::Transfer {
267 from: H160::default(),262 from: H160::default(),
268 to: *user.as_eth(),263 to: *user.as_eth(),
269 value: amount.into(),264 value: amount.into(),
287 ) {282 ) {
288 <Allowance<T>>::insert((collection.id, owner, spender), amount);283 <Allowance<T>>::insert((collection.id, owner, spender), amount);
289284
290 collection.log_infallible(ERC20Events::Approval {285 collection.log(ERC20Events::Approval {
291 owner: *owner.as_eth(),286 owner: *owner.as_eth(),
292 spender: *spender.as_eth(),287 spender: *spender.as_eth(),
293 value: amount.into(),288 value: amount.into(),
314309
315 if <Balance<T>>::get((collection.id, owner)) < amount {310 if <Balance<T>>::get((collection.id, owner)) < amount {
316 ensure!(311 ensure!(
317 collection.ignores_owned_amount(owner)?,312 collection.ignores_owned_amount(owner),
318 <CommonError<T>>::CantApproveMoreThanOwned313 <CommonError<T>>::CantApproveMoreThanOwned
319 );314 );
320 }315 }
343 let allowance = <Allowance<T>>::get((collection.id, from, spender)).checked_sub(amount);338 let allowance = <Allowance<T>>::get((collection.id, from, spender)).checked_sub(amount);
344 if allowance.is_none() {339 if allowance.is_none() {
345 ensure!(340 ensure!(
346 collection.ignores_allowance(spender)?,341 collection.ignores_allowance(spender),
347 <CommonError<T>>::TokenValueNotEnough342 <CommonError<T>>::TokenValueNotEnough
348 );343 );
349 }344 }
374 let allowance = <Allowance<T>>::get((collection.id, from, spender)).checked_sub(amount);369 let allowance = <Allowance<T>>::get((collection.id, from, spender)).checked_sub(amount);
375 if allowance.is_none() {370 if allowance.is_none() {
376 ensure!(371 ensure!(
377 collection.ignores_allowance(spender)?,372 collection.ignores_allowance(spender),
378 <CommonError<T>>::TokenValueNotEnough373 <CommonError<T>>::TokenValueNotEnough
379 );374 );
380 }375 }
modifiedpallets/nft/Cargo.tomldiffbeforeafterboth
146 "serde_no_std",146 "serde_no_std",
147] }147] }
148148
149pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }149pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
150pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }150pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
151fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }151fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
152hex-literal = "0.3.3"152hex-literal = "0.3.3"
153153
154pallet-common = { default-features = false, path = "../common" }154pallet-common = { default-features = false, path = "../common" }
modifiedpallets/nft/src/benchmarking.rsdiffbeforeafterboth
155155
156 let cl = CollectionLimits {156 let cl = CollectionLimits {
157 account_token_ownership_limit: Some(0),157 account_token_ownership_limit: Some(0),
158 sponsored_data_size: 0,158 sponsored_data_size: Some(0),
159 token_limit: 1,159 token_limit: Some(1),
160 sponsor_transfer_timeout: 0,160 sponsor_transfer_timeout: Some(0),
161 owner_can_destroy: true,161 owner_can_destroy: Some(true),
162 owner_can_transfer: true,162 owner_can_transfer: Some(true),
163 sponsored_data_rate_limit: None,163 sponsored_data_rate_limit: None,
164 transfers_enabled: Some(true),
164 };165 };
165 }: set_collection_limits(RawOrigin::Signed(caller.clone()), collection, cl)166 }: set_collection_limits(RawOrigin::Signed(caller.clone()), collection, cl)
166167
modifiedpallets/nft/src/dispatch.rsdiffbeforeafterboth
83 _ => {}83 _ => {}
84 }84 }
8585
86 // TODO: Make submit_logs infallible, but it shouldn't fail here anyway
87 dispatched86 dispatched.into_inner().submit_logs();
88 .into_inner()
89 .submit_logs()
90 .expect("should succeed");
91 result87 result
92}88}
9389
modifiedpallets/nft/src/eth/sponsoring.rsdiffbeforeafterboth
31 let (method_id, mut reader) = AbiReader::new_call(call).map_err(|_| AnyError)?;31 let (method_id, mut reader) = AbiReader::new_call(call).map_err(|_| AnyError)?;
32 match &collection.mode {32 match &collection.mode {
33 crate::CollectionMode::NFT => {33 crate::CollectionMode::NFT => {
34 let call: UniqueNFTCall = UniqueNFTCall::parse(method_id, &mut reader)34 let call = <UniqueNFTCall<T>>::parse(method_id, &mut reader)
35 .map_err(|_| AnyError)?35 .map_err(|_| AnyError)?
36 .ok_or(AnyError)?;36 .ok_or(AnyError)?;
37 match call {37 match call {
63 }63 }
64 }64 }
65 crate::CollectionMode::Fungible(_) => {65 crate::CollectionMode::Fungible(_) => {
66 let call: UniqueFungibleCall = UniqueFungibleCall::parse(method_id, &mut reader)66 let call = <UniqueFungibleCall<T>>::parse(method_id, &mut reader)
67 .map_err(|_| AnyError)?67 .map_err(|_| AnyError)?
68 .ok_or(AnyError)?;68 .ok_or(AnyError)?;
69 #[allow(clippy::single_match)]69 #[allow(clippy::single_match)]
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
2 char::{REPLACEMENT_CHARACTER, decode_utf16},2 char::{REPLACEMENT_CHARACTER, decode_utf16},
3 convert::TryInto,3 convert::TryInto,
4};4};
5use evm_coder::{ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*};5use evm_coder::{ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*, weight};
6use frame_support::BoundedVec;6use frame_support::BoundedVec;
7use nft_data_structs::TokenId;7use nft_data_structs::TokenId;
8use pallet_evm_coder_substrate::dispatch_to_evm;8use pallet_evm_coder_substrate::dispatch_to_evm;
9use sp_core::{H160, U256};9use sp_core::{H160, U256};
10use sp_std::{vec::Vec, vec};10use sp_std::{vec::Vec, vec};
11use pallet_common::{account::CrossAccountId, erc::CommonEvmHandler};11use pallet_common::{account::CrossAccountId, erc::CommonEvmHandler};
12use pallet_evm_coder_substrate::call_internal;12use pallet_evm_coder_substrate::call;
13use pallet_common::erc::PrecompileOutput;13use pallet_common::erc::PrecompileOutput;
1414
15use crate::{15use crate::{
16 AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,16 AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,
17 SelfWeightOf, weights::WeightInfo,
17};18};
1819
19#[derive(ToLog)]20#[derive(ToLog)]
64 /// Returns token's const_metadata65 /// Returns token's const_metadata
65 #[solidity(rename_selector = "tokenURI")]66 #[solidity(rename_selector = "tokenURI")]
66 fn token_uri(&self, token_id: uint256) -> Result<string> {67 fn token_uri(&self, token_id: uint256) -> Result<string> {
68 self.consume_store_reads(1)?;
67 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;69 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
68 Ok(string::from_utf8_lossy(70 Ok(string::from_utf8_lossy(
69 &<TokenData<T>>::get((self.id, token_id))71 &<TokenData<T>>::get((self.id, token_id))
87 }89 }
8890
89 fn total_supply(&self) -> Result<uint256> {91 fn total_supply(&self) -> Result<uint256> {
92 self.consume_store_reads(1)?;
90 Ok(<Pallet<T>>::total_supply(self).into())93 Ok(<Pallet<T>>::total_supply(self).into())
91 }94 }
92}95}
9396
94#[solidity_interface(name = "ERC721", events(ERC721Events))]97#[solidity_interface(name = "ERC721", events(ERC721Events))]
95impl<T: Config> NonfungibleHandle<T> {98impl<T: Config> NonfungibleHandle<T> {
96 fn balance_of(&self, owner: address) -> Result<uint256> {99 fn balance_of(&self, owner: address) -> Result<uint256> {
100 self.consume_store_reads(1)?;
97 let owner = T::CrossAccountId::from_eth(owner);101 let owner = T::CrossAccountId::from_eth(owner);
98 let balance = <AccountBalance<T>>::get((self.id, owner));102 let balance = <AccountBalance<T>>::get((self.id, owner));
99 Ok(balance.into())103 Ok(balance.into())
100 }104 }
101 fn owner_of(&self, token_id: uint256) -> Result<address> {105 fn owner_of(&self, token_id: uint256) -> Result<address> {
106 self.consume_store_reads(1)?;
102 let token: TokenId = token_id.try_into()?;107 let token: TokenId = token_id.try_into()?;
103 Ok(*<TokenData<T>>::get((self.id, token))108 Ok(*<TokenData<T>>::get((self.id, token))
104 .ok_or("token not found")?109 .ok_or("token not found")?
129 Err("not implemented".into())134 Err("not implemented".into())
130 }135 }
131136
137 #[weight(<SelfWeightOf<T>>::transfer_from())]
132 fn transfer_from(138 fn transfer_from(
133 &mut self,139 &mut self,
134 caller: caller,140 caller: caller,
147 Ok(())153 Ok(())
148 }154 }
149155
156 #[weight(<SelfWeightOf<T>>::approve())]
150 fn approve(157 fn approve(
151 &mut self,158 &mut self,
152 caller: caller,159 caller: caller,
189196
190#[solidity_interface(name = "ERC721Burnable")]197#[solidity_interface(name = "ERC721Burnable")]
191impl<T: Config> NonfungibleHandle<T> {198impl<T: Config> NonfungibleHandle<T> {
199 #[weight(<SelfWeightOf<T>>::burn_item())]
192 fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {200 fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {
193 let caller = T::CrossAccountId::from_eth(caller);201 let caller = T::CrossAccountId::from_eth(caller);
194 let token = token_id.try_into()?;202 let token = token_id.try_into()?;
206214
207 /// `token_id` should be obtained with `next_token_id` method,215 /// `token_id` should be obtained with `next_token_id` method,
208 /// unlike standard, you can't specify it manually216 /// unlike standard, you can't specify it manually
217 #[weight(<SelfWeightOf<T>>::create_item())]
209 fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {218 fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {
210 let caller = T::CrossAccountId::from_eth(caller);219 let caller = T::CrossAccountId::from_eth(caller);
211 let to = T::CrossAccountId::from_eth(to);220 let to = T::CrossAccountId::from_eth(to);
235 /// `token_id` should be obtained with `next_token_id` method,244 /// `token_id` should be obtained with `next_token_id` method,
236 /// unlike standard, you can't specify it manually245 /// unlike standard, you can't specify it manually
237 #[solidity(rename_selector = "mintWithTokenURI")]246 #[solidity(rename_selector = "mintWithTokenURI")]
247 #[weight(<SelfWeightOf<T>>::create_item())]
238 fn mint_with_token_uri(248 fn mint_with_token_uri(
239 &mut self,249 &mut self,
240 caller: caller,250 caller: caller,
276286
277#[solidity_interface(name = "ERC721UniqueExtensions")]287#[solidity_interface(name = "ERC721UniqueExtensions")]
278impl<T: Config> NonfungibleHandle<T> {288impl<T: Config> NonfungibleHandle<T> {
289 #[weight(<SelfWeightOf<T>>::transfer())]
279 fn transfer(290 fn transfer(
280 &mut self,291 &mut self,
281 caller: caller,292 caller: caller,
291 Ok(())302 Ok(())
292 }303 }
293304
305 #[weight(<SelfWeightOf<T>>::burn_from())]
294 fn burn_from(306 fn burn_from(
295 &mut self,307 &mut self,
296 caller: caller,308 caller: caller,
307 }319 }
308320
309 fn next_token_id(&self) -> Result<uint256> {321 fn next_token_id(&self) -> Result<uint256> {
322 self.consume_store_reads(1)?;
310 Ok(<TokensMinted<T>>::get(self.id)323 Ok(<TokensMinted<T>>::get(self.id)
311 .checked_add(1)324 .checked_add(1)
312 .ok_or("item id overflow")?325 .ok_or("item id overflow")?
313 .into())326 .into())
314 }327 }
315328
329 #[weight(<SelfWeightOf<T>>::set_variable_metadata(data.len() as u32))]
316 fn set_variable_metadata(330 fn set_variable_metadata(
317 &mut self,331 &mut self,
318 caller: caller,332 caller: caller,
328 }342 }
329343
330 fn get_variable_metadata(&self, token_id: uint256) -> Result<bytes> {344 fn get_variable_metadata(&self, token_id: uint256) -> Result<bytes> {
345 self.consume_store_reads(1)?;
331 let token: TokenId = token_id.try_into()?;346 let token: TokenId = token_id.try_into()?;
332347
333 Ok(<TokenData<T>>::get((self.id, token))348 Ok(<TokenData<T>>::get((self.id, token))
334 .ok_or("token not found")?349 .ok_or("token not found")?
335 .variable_data)350 .variable_data)
336 }351 }
337352
353 #[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]
338 fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {354 fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {
339 let caller = T::CrossAccountId::from_eth(caller);355 let caller = T::CrossAccountId::from_eth(caller);
340 let to = T::CrossAccountId::from_eth(to);356 let to = T::CrossAccountId::from_eth(to);
363 }379 }
364380
365 #[solidity(rename_selector = "mintBulkWithTokenURI")]381 #[solidity(rename_selector = "mintBulkWithTokenURI")]
382 #[weight(<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32))]
366 fn mint_bulk_with_token_uri(383 fn mint_bulk_with_token_uri(
367 &mut self,384 &mut self,
368 caller: caller,385 caller: caller,
411impl<T: Config> NonfungibleHandle<T> {}428impl<T: Config> NonfungibleHandle<T> {}
412429
413// Not a tests, but code generators430// Not a tests, but code generators
414generate_stubgen!(gen_impl, UniqueNFTCall, true);431generate_stubgen!(gen_impl, UniqueNFTCall<()>, true);
415generate_stubgen!(gen_iface, UniqueNFTCall, false);432generate_stubgen!(gen_iface, UniqueNFTCall<()>, false);
416
417pub const CODE: &[u8] = include_bytes!("./stubs/UniqueNFT.raw");
418433
419impl<T: Config> CommonEvmHandler for NonfungibleHandle<T> {434impl<T: Config> CommonEvmHandler for NonfungibleHandle<T> {
420 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueNFT.raw");435 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueNFT.raw");
421436
422 fn call(mut self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileOutput> {437 fn call(self, source: &H160, input: &[u8], value: U256) -> Option<PrecompileOutput> {
423 let result = call_internal::<UniqueNFTCall, _>(*source, &mut self, value, input);438 call::<T, UniqueNFTCall<T>, _>(*source, self, value, input)
424 self.0.recorder.evm_to_precompile_output(result)
425 }439 }
426}440}
427441
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
8use pallet_common::{8use pallet_common::{
9 Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, account::CrossAccountId,9 Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, account::CrossAccountId,
10};10};
11use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
11use sp_core::H160;12use sp_core::H160;
12use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};13use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};
13use sp_std::{vec::Vec, vec};14use sp_std::{vec::Vec, vec};
114 self.0115 self.0
115 }116 }
116}117}
118impl<T: Config> WithRecorder<T> for NonfungibleHandle<T> {
119 fn recorder(&self) -> &SubstrateRecorder<T> {
120 self.0.recorder()
121 }
122 fn into_recorder(self) -> SubstrateRecorder<T> {
123 self.0.into_recorder()
124 }
125}
117impl<T: Config> Deref for NonfungibleHandle<T> {126impl<T: Config> Deref for NonfungibleHandle<T> {
118 type Target = pallet_common::CollectionHandle<T>;127 type Target = pallet_common::CollectionHandle<T>;
119128
165 ensure!(174 ensure!(
166 &token_data.owner == sender175 &token_data.owner == sender
167 || (collection.limits.owner_can_transfer()176 || (collection.limits.owner_can_transfer() && collection.is_owner_or_admin(sender)),
168 && collection.is_owner_or_admin(sender)?),
169 <CommonError<T>>::NoPermission177 <CommonError<T>>::NoPermission
170 );178 );
171179
194 ));202 ));
195 }203 }
196204
197 collection.log_infallible(ERC721Events::Transfer {205 collection.log(ERC721Events::Transfer {
198 from: *token_data.owner.as_eth(),206 from: *token_data.owner.as_eth(),
199 to: H160::default(),207 to: H160::default(),
200 token_id: token.into(),208 token_id: token.into(),
224 ensure!(232 ensure!(
225 &token_data.owner == from233 &token_data.owner == from
226 || (collection.limits.owner_can_transfer()234 || (collection.limits.owner_can_transfer() && collection.is_owner_or_admin(from)),
227 && collection.is_owner_or_admin(from)?),
228 <CommonError<T>>::NoPermission235 <CommonError<T>>::NoPermission
229 );236 );
230237
252 None259 None
253 };260 };
254
255 collection.consume_sstores(4)?;
256 collection.consume_log(3, 0)?;
257261
258 // =========262 // =========
259263
278 }282 }
279 Self::set_allowance_unchecked(collection, from, token, None, true);283 Self::set_allowance_unchecked(collection, from, token, None, true);
280284
281 collection.log_infallible(ERC721Events::Transfer {285 collection.log(ERC721Events::Transfer {
282 from: *from.as_eth(),286 from: *from.as_eth(),
283 to: *to.as_eth(),287 to: *to.as_eth(),
284 token_id: token.into(),288 token_id: token.into(),
298 sender: &T::CrossAccountId,302 sender: &T::CrossAccountId,
299 data: Vec<CreateItemData<T>>,303 data: Vec<CreateItemData<T>>,
300 ) -> DispatchResult {304 ) -> DispatchResult {
301 let unrestricted_minting = collection.is_owner_or_admin(sender)?;305 if !collection.is_owner_or_admin(sender) {
302 if !unrestricted_minting {
303 ensure!(306 ensure!(
304 collection.mint_mode,307 collection.mint_mode,
305 <CommonError<T>>::PublicMintingNotAllowed308 <CommonError<T>>::PublicMintingNotAllowed
313316
314 for data in data.iter() {317 for data in data.iter() {
315 <PalletCommon<T>>::ensure_correct_receiver(&data.owner)?;318 <PalletCommon<T>>::ensure_correct_receiver(&data.owner)?;
316 if !data.const_data.is_empty() {
317 collection.consume_sstore()?;
318 }
319 if !data.variable_data.is_empty() {
320 collection.consume_sstore()?;
321 }
322 collection.consume_sstore()?;
323 collection.consume_log(3, 0)?;
324 }319 }
325320
326 let first_token = <TokensMinted<T>>::get(collection.id);321 let first_token = <TokensMinted<T>>::get(collection.id);
331 tokens_minted < collection.limits.token_limit(),326 tokens_minted < collection.limits.token_limit(),
332 <CommonError<T>>::CollectionTokenLimitExceeded327 <CommonError<T>>::CollectionTokenLimitExceeded
333 );328 );
334 collection.consume_sstore()?;
335329
336 let mut balances = BTreeMap::new();330 let mut balances = BTreeMap::new();
337 for data in &data {331 for data in &data {
345 <CommonError<T>>::AccountTokenLimitExceeded,339 <CommonError<T>>::AccountTokenLimitExceeded,
346 );340 );
347 }341 }
348 collection.consume_sstores(balances.len())?;
349342
350 // =========343 // =========
351344
366 );359 );
367 <Owned<T>>::insert((collection.id, &data.owner, token), true);360 <Owned<T>>::insert((collection.id, &data.owner, token), true);
368361
369 collection.log_infallible(ERC721Events::Transfer {362 collection.log(ERC721Events::Transfer {
370 from: H160::default(),363 from: H160::default(),
371 to: *data.owner.as_eth(),364 to: *data.owner.as_eth(),
372 token_id: token.into(),365 token_id: token.into(),
393 <Allowance<T>>::insert((collection.id, token), spender);386 <Allowance<T>>::insert((collection.id, token), spender);
394 // In ERC721 there is only one possible approved user of token, so we set387 // In ERC721 there is only one possible approved user of token, so we set
395 // approved user to spender388 // approved user to spender
396 collection.log_infallible(ERC721Events::Approval {389 collection.log(ERC721Events::Approval {
397 owner: *sender.as_eth(),390 owner: *sender.as_eth(),
398 approved: *spender.as_eth(),391 approved: *spender.as_eth(),
399 token_id: token.into(),392 token_id: token.into(),
423 if !assume_implicit_eth {416 if !assume_implicit_eth {
424 // In ERC721 there is only one possible approved user of token, so we set417 // In ERC721 there is only one possible approved user of token, so we set
425 // approved user to zero address418 // approved user to zero address
426 collection.log_infallible(ERC721Events::Approval {419 collection.log(ERC721Events::Approval {
427 owner: *sender.as_eth(),420 owner: *sender.as_eth(),
428 approved: H160::default(),421 approved: H160::default(),
429 token_id: token.into(),422 token_id: token.into(),
463 <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;456 <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;
464 if &token_data.owner != sender {457 if &token_data.owner != sender {
465 ensure!(458 ensure!(
466 collection.ignores_owned_amount(sender)?,459 collection.ignores_owned_amount(sender),
467 <CommonError<T>>::CantApproveMoreThanOwned460 <CommonError<T>>::CantApproveMoreThanOwned
468 );461 );
469 }462 }
491484
492 if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {485 if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {
493 ensure!(486 ensure!(
494 collection.ignores_allowance(spender)?,487 collection.ignores_allowance(spender),
495 <CommonError<T>>::TokenValueNotEnough488 <CommonError<T>>::TokenValueNotEnough
496 );489 );
497 }490 }
519512
520 if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {513 if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {
521 ensure!(514 ensure!(
522 collection.ignores_allowance(spender)?,515 collection.ignores_allowance(spender),
523 <CommonError<T>>::TokenValueNotEnough516 <CommonError<T>>::TokenValueNotEnough
524 );517 );
525 }518 }
543 <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;536 <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;
544 collection.check_can_update_meta(sender, &token_data.owner)?;537 collection.check_can_update_meta(sender, &token_data.owner)?;
545
546 collection.consume_sstore()?;
547538
548 // =========539 // =========
549540
modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
58 }58 }
5959
60 fn burn_from() -> Weight {60 fn burn_from() -> Weight {
61 061 <SelfWeightOf<T>>::burn_from()
62 }62 }
6363
64 fn set_variable_metadata(bytes: u32) -> Weight {64 fn set_variable_metadata(bytes: u32) -> Weight {
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
359 sender: &T::CrossAccountId,359 sender: &T::CrossAccountId,
360 data: Vec<CreateItemData<T>>,360 data: Vec<CreateItemData<T>>,
361 ) -> DispatchResult {361 ) -> DispatchResult {
362 let unrestricted_minting = collection.is_owner_or_admin(sender)?;362 if !collection.is_owner_or_admin(sender) {
363 if !unrestricted_minting {
364 ensure!(363 ensure!(
365 collection.mint_mode,364 collection.mint_mode,
366 <CommonError<T>>::PublicMintingNotAllowed365 <CommonError<T>>::PublicMintingNotAllowed
492491
493 if <Balance<T>>::get((collection.id, token, sender)) < amount {492 if <Balance<T>>::get((collection.id, token, sender)) < amount {
494 ensure!(493 ensure!(
495 collection.ignores_owned_amount(sender)? && Self::token_exists(collection, token),494 collection.ignores_owned_amount(sender) && Self::token_exists(collection, token),
496 <CommonError<T>>::CantApproveMoreThanOwned495 <CommonError<T>>::CantApproveMoreThanOwned
497 );496 );
498 }497 }
523 <Allowance<T>>::get((collection.id, token, from, &spender)).checked_sub(amount);522 <Allowance<T>>::get((collection.id, token, from, &spender)).checked_sub(amount);
524 if allowance.is_none() {523 if allowance.is_none() {
525 ensure!(524 ensure!(
526 collection.ignores_allowance(spender)?,525 collection.ignores_allowance(spender),
527 <CommonError<T>>::TokenValueNotEnough526 <CommonError<T>>::TokenValueNotEnough
528 );527 );
529 }528 }
556 <Allowance<T>>::get((collection.id, token, from, &spender)).checked_sub(amount);555 <Allowance<T>>::get((collection.id, token, from, &spender)).checked_sub(amount);
557 if allowance.is_none() {556 if allowance.is_none() {
558 ensure!(557 ensure!(
559 collection.ignores_allowance(spender)?,558 collection.ignores_allowance(spender),
560 <CommonError<T>>::TokenValueNotEnough559 <CommonError<T>>::TokenValueNotEnough
561 );560 );
562 }561 }
585 &T::CrossAccountId::from_sub(collection.owner.clone()),584 &T::CrossAccountId::from_sub(collection.owner.clone()),
586 )?;585 )?;
587586
588 collection.consume_sstore()?;
589 let token_data = <TokenData<T>>::get((collection.id, token));587 let token_data = <TokenData<T>>::get((collection.id, token));
590588
591 // =========589 // =========
modifiedruntime/Cargo.tomldiffbeforeafterboth
387pallet-evm-transaction-payment = { path = '../pallets/evm-transaction-payment', default-features = false }387pallet-evm-transaction-payment = { path = '../pallets/evm-transaction-payment', default-features = false }
388pallet-evm-coder-substrate = { default-features = false, path = "../pallets/evm-coder-substrate" }388pallet-evm-coder-substrate = { default-features = false, path = "../pallets/evm-coder-substrate" }
389389
390pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }390pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
391pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }391pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
392fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }392fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
393fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12" }393fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.12-weights" }
394394
395################################################################################395################################################################################
396# Build Dependencies396# Build Dependencies
modifiedruntime/src/lib.rsdiffbeforeafterboth
66};66};
67use smallvec::smallvec;67use smallvec::smallvec;
68use codec::{Encode, Decode};68use codec::{Encode, Decode};
69use pallet_evm::{Account as EVMAccount, FeeCalculator, OnMethodCall};69use pallet_evm::{Account as EVMAccount, FeeCalculator, GasWeightMapping, OnMethodCall};
70use fp_rpc::TransactionStatus;70use fp_rpc::TransactionStatus;
71use sp_core::crypto::Public;71use sp_core::crypto::Public;
72use sp_runtime::{72use sp_runtime::{
247 }247 }
248}248}
249
250// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case
251// (contract, which only writes a lot of data),
252// approximating on top of our real store write weight
253parameter_types! {
254 pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;
255 pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;
256 pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();
257}
258
259/// Limiting EVM execution to 50% of block for substrate users and management tasks
260/// EVM transaction consumes more weight than substrate's, so we can't rely on them being
261/// scheduled fairly
262const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);
263parameter_types! {
264 pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());
265}
266
267pub enum FixedGasWeightMapping {}
268impl GasWeightMapping for FixedGasWeightMapping {
269 fn gas_to_weight(gas: u64) -> Weight {
270 gas.saturating_mul(WeightPerGas::get())
271 }
272 fn weight_to_gas(weight: Weight) -> u64 {
273 weight / WeightPerGas::get()
274 }
275}
249276
250impl pallet_evm::Config for Runtime {277impl pallet_evm::Config for Runtime {
251 type BlockGasLimit = BlockGasLimit;278 type BlockGasLimit = BlockGasLimit;
252 type FeeCalculator = FixedFee;279 type FeeCalculator = FixedFee;
253 type GasWeightMapping = ();280 type GasWeightMapping = FixedGasWeightMapping;
254 type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;281 type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
255 type CallOrigin = EnsureAddressTruncated;282 type CallOrigin = EnsureAddressTruncated;
256 type WithdrawOrigin = EnsureAddressTruncated;283 type WithdrawOrigin = EnsureAddressTruncated;
289 }316 }
290}317}
291
292parameter_types! {
293 pub BlockGasLimit: U256 = U256::from(u32::max_value());
294}
295318
296impl pallet_ethereum::Config for Runtime {319impl pallet_ethereum::Config for Runtime {
297 type Event = Event;320 type Event = Event;
298 type StateRoot = pallet_ethereum::IntermediateStateRoot;321 type StateRoot = pallet_ethereum::IntermediateStateRoot;
299 type EvmSubmitLog = pallet_evm::Pallet<Self>;
300}322}
301323
302impl pallet_randomness_collective_flip::Config for Runtime {}324impl pallet_randomness_collective_flip::Config for Runtime {}
671693
672impl pallet_evm_coder_substrate::Config for Runtime {694impl pallet_evm_coder_substrate::Config for Runtime {
673 type EthereumTransactionSender = pallet_ethereum::Pallet<Self>;695 type EthereumTransactionSender = pallet_ethereum::Pallet<Self>;
696 type GasWeightMapping = FixedGasWeightMapping;
674}697}
675698
676impl pallet_xcm::Config for Runtime {699impl pallet_xcm::Config for Runtime {