difftreelog
misk: Remove some warnings. Add over_max_size test
in: master
12 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2347,6 +2347,7 @@
"sha3-const",
"similar-asserts",
"sp-std",
+ "trybuild",
]
[[package]]
@@ -12671,6 +12672,21 @@
]
[[package]]
+name = "trybuild"
+version = "1.0.71"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea496675d71016e9bc76aa42d87f16aefd95447cc5818e671e12b2d7e269075d"
+dependencies = [
+ "glob",
+ "once_cell",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "termcolor",
+ "toml",
+]
+
+[[package]]
name = "tt-call"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
crates/evm-coder/Cargo.tomldiffbeforeafterboth--- a/crates/evm-coder/Cargo.toml
+++ b/crates/evm-coder/Cargo.toml
@@ -29,6 +29,7 @@
hex-literal = "0.3.4"
similar-asserts = "1.4.2"
concat-idents = "1.1.3"
+trybuild = "1.0"
[features]
default = ["std"]
crates/evm-coder/src/custom_signature.rsdiffbeforeafterboth--- a/crates/evm-coder/src/custom_signature.rs
+++ b/crates/evm-coder/src/custom_signature.rs
@@ -423,15 +423,6 @@
assert_eq!(<MaxSize>::name(), "!".repeat(SIGNATURE_SIZE_LIMIT));
}
- // This test must NOT compile with "index out of bounds"!
- // #[test]
- // fn over_max_size() {
- // assert_eq!(
- // <Vec<MaxSize>>::name(),
- // "!".repeat(SIGNATURE_SIZE_LIMIT) + "[]"
- // );
- // }
-
#[test]
fn make_func_without_args() {
const SIG: FunctionSignature = make_signature!(
@@ -498,4 +489,10 @@
fn shift() {
assert_eq!(<(u32,)>::name(), "(uint32)");
}
+
+ #[test]
+ fn over_max_size() {
+ let t = trybuild::TestCases::new();
+ t.compile_fail("tests/build_failed/custom_signature_over_max_size.rs");
+ }
}
crates/evm-coder/tests/build_failed/custom_signature_over_max_size.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/evm-coder/tests/build_failed/custom_signature_over_max_size.rs
@@ -0,0 +1,33 @@
+#![allow(dead_code)]
+use std::str::from_utf8;
+
+use evm_coder::{
+ make_signature,
+ custom_signature::{SignatureUnit, SIGNATURE_SIZE_LIMIT},
+};
+
+trait Name {
+ const SIGNATURE: SignatureUnit;
+
+ fn name() -> &'static str {
+ from_utf8(&Self::SIGNATURE.data[..Self::SIGNATURE.len]).expect("bad utf-8")
+ }
+}
+
+impl<T: Name> Name for Vec<T> {
+ evm_coder::make_signature!(new nameof(T) fixed("[]"));
+}
+
+struct MaxSize();
+impl Name for MaxSize {
+ const SIGNATURE: SignatureUnit = SignatureUnit {
+ data: [b'!'; SIGNATURE_SIZE_LIMIT],
+ len: SIGNATURE_SIZE_LIMIT,
+ };
+}
+
+const NAME: SignatureUnit = <Vec<MaxSize>>::SIGNATURE;
+
+fn main() {
+ assert!(false);
+}
crates/evm-coder/tests/build_failed/custom_signature_over_max_size.stderrdiffbeforeafterboth--- /dev/null
+++ b/crates/evm-coder/tests/build_failed/custom_signature_over_max_size.stderr
@@ -0,0 +1,19 @@
+error: any use of this value will cause an error
+ --> tests/build_failed/custom_signature_over_max_size.rs:18:2
+ |
+18 | evm_coder::make_signature!(new nameof(T) fixed("[]"));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 256 but the index is 256
+ |
+ = note: `#[deny(const_err)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ = note: this error originates in the macro `make_signature` which comes from the expansion of the macro `evm_coder::make_signature` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: any use of this value will cause an error
+ --> tests/build_failed/custom_signature_over_max_size.rs:29:29
+ |
+29 | const NAME: SignatureUnit = <Vec<MaxSize>>::SIGNATURE;
+ | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -35,10 +35,7 @@
use crate::{
Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,
- eth::{
- convert_cross_account_to_uint256, convert_cross_account_to_tuple,
- convert_tuple_to_cross_account,
- },
+ eth::{convert_cross_account_to_uint256, convert_tuple_to_cross_account},
weights::WeightInfo,
};
pallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -17,7 +17,6 @@
//! Implementation of magic contract
extern crate alloc;
-use alloc::string::ToString;
use core::marker::PhantomData;
use evm_coder::{
abi::AbiWriter,
pallets/fungible/src/erc.rsdiffbeforeafterboth--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -28,7 +28,6 @@
custom_signature::{SignatureUnit, FunctionSignature, SignaturePreferences},
make_signature,
};
-use pallet_common::eth::convert_tuple_to_cross_account;
use up_data_structs::CollectionMode;
use pallet_common::erc::{CommonEvmHandler, PrecompileResult};
use sp_std::vec::Vec;
pallets/refungible/src/erc.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -21,7 +21,6 @@
extern crate alloc;
-use alloc::string::ToString;
use core::{
char::{REPLACEMENT_CHARACTER, decode_utf16},
convert::TryInto,
@@ -39,7 +38,6 @@
use pallet_common::{
CollectionHandle, CollectionPropertyPermissions,
erc::{CommonEvmHandler, CollectionCall, static_property::key},
- eth::convert_tuple_to_cross_account,
};
use pallet_evm::{account::CrossAccountId, PrecompileHandle};
use pallet_evm_coder_substrate::{call, dispatch_to_evm};
pallets/unique/src/eth/mod.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! Implementation of CollectionHelpers contract.1819use core::marker::PhantomData;20use ethereum as _;21use evm_coder::{22 execution::*,23 generate_stubgen, solidity, solidity_interface,24 types::*,25 custom_signature::{SignatureUnit, FunctionSignature, SignaturePreferences},26 make_signature, weight,27};28use frame_support::traits::Get;29use crate::Pallet;3031use pallet_common::{32 CollectionById,33 dispatch::CollectionDispatch,34 erc::{static_property::key, CollectionHelpersEvents},35 Pallet as PalletCommon,36};37use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};38use pallet_evm_coder_substrate::{dispatch_to_evm, SubstrateRecorder, WithRecorder};39use sp_std::vec;40use up_data_structs::{41 CollectionDescription, CollectionMode, CollectionName, CollectionTokenPrefix,42 CreateCollectionData,43};4445use crate::{weights::WeightInfo, Config, SelfWeightOf};4647use alloc::format;48use sp_std::vec::Vec;4950/// See [`CollectionHelpersCall`]51pub struct EvmCollectionHelpers<T: Config>(SubstrateRecorder<T>);52impl<T: Config> WithRecorder<T> for EvmCollectionHelpers<T> {53 fn recorder(&self) -> &SubstrateRecorder<T> {54 &self.055 }5657 fn into_recorder(self) -> SubstrateRecorder<T> {58 self.059 }60}6162fn convert_data<T: Config>(63 caller: caller,64 name: string,65 description: string,66 token_prefix: string,67) -> Result<(68 T::CrossAccountId,69 CollectionName,70 CollectionDescription,71 CollectionTokenPrefix,72)> {73 let caller = T::CrossAccountId::from_eth(caller);74 let name = name75 .encode_utf16()76 .collect::<Vec<u16>>()77 .try_into()78 .map_err(|_| error_field_too_long(stringify!(name), CollectionName::bound()))?;79 let description = description80 .encode_utf16()81 .collect::<Vec<u16>>()82 .try_into()83 .map_err(|_| {84 error_field_too_long(stringify!(description), CollectionDescription::bound())85 })?;86 let token_prefix = token_prefix.into_bytes().try_into().map_err(|_| {87 error_field_too_long(stringify!(token_prefix), CollectionTokenPrefix::bound())88 })?;89 Ok((caller, name, description, token_prefix))90}9192#[inline(always)]93fn create_collection_internal<T: Config>(94 caller: caller,95 value: value,96 name: string,97 collection_mode: CollectionMode,98 description: string,99 token_prefix: string,100) -> Result<address> {101 let (caller, name, description, token_prefix) =102 convert_data::<T>(caller, name, description, token_prefix)?;103 let data = CreateCollectionData {104 name,105 mode: collection_mode,106 description,107 token_prefix,108 ..Default::default()109 };110 check_sent_amount_equals_collection_creation_price::<T>(value)?;111 let collection_helpers_address =112 T::CrossAccountId::from_eth(<T as pallet_common::Config>::ContractAddress::get());113114 let collection_id = T::CollectionDispatch::create(115 caller.clone(),116 collection_helpers_address,117 data,118 Default::default(),119 )120 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;121 let address = pallet_common::eth::collection_id_to_address(collection_id);122 Ok(address)123}124125fn check_sent_amount_equals_collection_creation_price<T: Config>(value: value) -> Result<()> {126 let value = value.as_u128();127 let creation_price: u128 = T::CollectionCreationPrice::get()128 .try_into()129 .map_err(|_| ()) // workaround for `expect` requiring `Debug` trait130 .expect("Collection creation price should be convertible to u128");131 if value != creation_price {132 return Err(format!(133 "Sent amount not equals to collection creation price ({0})",134 creation_price135 )136 .into());137 }138 Ok(())139}140141/// @title Contract, which allows users to operate with collections142#[solidity_interface(name = CollectionHelpers, events(CollectionHelpersEvents))]143impl<T> EvmCollectionHelpers<T>144where145 T: Config + pallet_common::Config + pallet_nonfungible::Config + pallet_refungible::Config,146{147 /// Create an NFT collection148 /// @param name Name of the collection149 /// @param description Informative description of the collection150 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications151 /// @return address Address of the newly created collection152 #[weight(<SelfWeightOf<T>>::create_collection())]153 #[solidity(rename_selector = "createNFTCollection")]154 fn create_nft_collection(155 &mut self,156 caller: caller,157 value: value,158 name: string,159 description: string,160 token_prefix: string,161 ) -> Result<address> {162 let (caller, name, description, token_prefix) =163 convert_data::<T>(caller, name, description, token_prefix)?;164 let data = CreateCollectionData {165 name,166 mode: CollectionMode::NFT,167 description,168 token_prefix,169 ..Default::default()170 };171 check_sent_amount_equals_collection_creation_price::<T>(value)?;172 let collection_helpers_address =173 T::CrossAccountId::from_eth(<T as pallet_common::Config>::ContractAddress::get());174 let collection_id = T::CollectionDispatch::create(175 caller,176 collection_helpers_address,177 data,178 Default::default(),179 )180 .map_err(dispatch_to_evm::<T>)?;181182 let address = pallet_common::eth::collection_id_to_address(collection_id);183 Ok(address)184 }185 /// Create an NFT collection186 /// @param name Name of the collection187 /// @param description Informative description of the collection188 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications189 /// @return address Address of the newly created collection190 #[weight(<SelfWeightOf<T>>::create_collection())]191 #[deprecated(note = "mathod was renamed to `create_nft_collection`, prefer it instead")]192 #[solidity(hide)]193 fn create_nonfungible_collection(194 &mut self,195 caller: caller,196 value: value,197 name: string,198 description: string,199 token_prefix: string,200 ) -> Result<address> {201 create_collection_internal::<T>(202 caller,203 value,204 name,205 CollectionMode::NFT,206 description,207 token_prefix,208 )209 }210211 #[weight(<SelfWeightOf<T>>::create_collection())]212 #[solidity(rename_selector = "createRFTCollection")]213 fn create_rft_collection(214 &mut self,215 caller: caller,216 value: value,217 name: string,218 description: string,219 token_prefix: string,220 ) -> Result<address> {221 create_collection_internal::<T>(222 caller,223 value,224 name,225 CollectionMode::ReFungible,226 description,227 token_prefix,228 )229 }230231 #[weight(<SelfWeightOf<T>>::create_collection())]232 #[solidity(rename_selector = "createFTCollection")]233 fn create_fungible_collection(234 &mut self,235 caller: caller,236 value: value,237 name: string,238 decimals: uint8,239 description: string,240 token_prefix: string,241 ) -> Result<address> {242 create_collection_internal::<T>(243 caller,244 value,245 name,246 CollectionMode::Fungible(decimals),247 description,248 token_prefix,249 )250 }251252 #[solidity(rename_selector = "makeCollectionERC721MetadataCompatible")]253 fn make_collection_metadata_compatible(254 &mut self,255 caller: caller,256 collection: address,257 base_uri: string,258 ) -> Result<()> {259 let caller = T::CrossAccountId::from_eth(caller);260 let collection =261 pallet_common::eth::map_eth_to_id(&collection).ok_or("not a collection address")?;262 let mut collection =263 <crate::CollectionHandle<T>>::new(collection).ok_or("collection not found")?;264265 if !matches!(266 collection.mode,267 CollectionMode::NFT | CollectionMode::ReFungible268 ) {269 return Err("target collection should be either NFT or Refungible".into());270 }271272 self.recorder().consume_sstore()?;273 collection274 .check_is_owner_or_admin(&caller)275 .map_err(dispatch_to_evm::<T>)?;276277 if collection.flags.erc721metadata {278 return Err("target collection is already Erc721Metadata compatible".into());279 }280 collection.flags.erc721metadata = true;281282 let all_permissions = <pallet_common::CollectionPropertyPermissions<T>>::get(collection.id);283 if all_permissions.get(&key::url()).is_none() {284 self.recorder().consume_sstore()?;285 <PalletCommon<T>>::set_property_permission(286 &collection,287 &caller,288 up_data_structs::PropertyKeyPermission {289 key: key::url(),290 permission: up_data_structs::PropertyPermission {291 mutable: true,292 collection_admin: true,293 token_owner: false,294 },295 },296 )297 .map_err(dispatch_to_evm::<T>)?;298 }299 if all_permissions.get(&key::suffix()).is_none() {300 self.recorder().consume_sstore()?;301 <PalletCommon<T>>::set_property_permission(302 &collection,303 &caller,304 up_data_structs::PropertyKeyPermission {305 key: key::suffix(),306 permission: up_data_structs::PropertyPermission {307 mutable: true,308 collection_admin: true,309 token_owner: false,310 },311 },312 )313 .map_err(dispatch_to_evm::<T>)?;314 }315316 let all_properties = <pallet_common::CollectionProperties<T>>::get(collection.id);317 if all_properties.get(&key::base_uri()).is_none() && !base_uri.is_empty() {318 self.recorder().consume_sstore()?;319 <PalletCommon<T>>::set_collection_properties(320 &collection,321 &caller,322 vec![up_data_structs::Property {323 key: key::base_uri(),324 value: base_uri325 .into_bytes()326 .try_into()327 .map_err(|_| "base uri is too large")?,328 }],329 )330 .map_err(dispatch_to_evm::<T>)?;331 }332333 self.recorder().consume_sstore()?;334 collection.save().map_err(dispatch_to_evm::<T>)?;335336 Ok(())337 }338339 #[weight(<SelfWeightOf<T>>::destroy_collection())]340 fn destroy_collection(&mut self, caller: caller, collection_address: address) -> Result<void> {341 let caller = T::CrossAccountId::from_eth(caller);342343 let collection_id = pallet_common::eth::map_eth_to_id(&collection_address)344 .ok_or("Invalid collection address format")?;345 <Pallet<T>>::destroy_collection_internal(caller, collection_id)346 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)347 }348349 /// Check if a collection exists350 /// @param collectionAddress Address of the collection in question351 /// @return bool Does the collection exist?352 fn is_collection_exist(&self, _caller: caller, collection_address: address) -> Result<bool> {353 if let Some(id) = pallet_common::eth::map_eth_to_id(&collection_address) {354 let collection_id = id;355 return Ok(<CollectionById<T>>::contains_key(collection_id));356 }357358 Ok(false)359 }360361 fn collection_creation_fee(&self) -> Result<value> {362 let price: u128 = T::CollectionCreationPrice::get()363 .try_into()364 .map_err(|_| ()) // workaround for `expect` requiring `Debug` trait365 .expect("Collection creation price should be convertible to u128");366 Ok(price.into())367 }368}369370/// Implements [`OnMethodCall`], which delegates call to [`EvmCollectionHelpers`]371pub struct CollectionHelpersOnMethodCall<T: Config>(PhantomData<*const T>);372impl<T: Config + pallet_nonfungible::Config + pallet_refungible::Config> OnMethodCall<T>373 for CollectionHelpersOnMethodCall<T>374{375 fn is_reserved(contract: &sp_core::H160) -> bool {376 contract == &T::ContractAddress::get()377 }378379 fn is_used(contract: &sp_core::H160) -> bool {380 contract == &T::ContractAddress::get()381 }382383 fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {384 if handle.code_address() != T::ContractAddress::get() {385 return None;386 }387388 let helpers =389 EvmCollectionHelpers::<T>(SubstrateRecorder::<T>::new(handle.remaining_gas()));390 pallet_evm_coder_substrate::call(handle, helpers)391 }392393 fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {394 (contract == &T::ContractAddress::get())395 .then(|| include_bytes!("./stubs/CollectionHelpers.raw").to_vec())396 }397}398399generate_stubgen!(collection_helper_impl, CollectionHelpersCall<()>, true);400generate_stubgen!(collection_helper_iface, CollectionHelpersCall<()>, false);401402fn error_field_too_long(feild: &str, bound: usize) -> Error {403 Error::Revert(format!("{} is too long. Max length is {}.", feild, bound))404}runtime/common/config/pallets/scheduler.rsdiffbeforeafterboth--- a/runtime/common/config/pallets/scheduler.rs
+++ b/runtime/common/config/pallets/scheduler.rs
@@ -25,7 +25,7 @@
use codec::Decode;
use crate::{
runtime_common::{scheduler::SchedulerPaymentExecutor, config::substrate::RuntimeBlockWeights},
- Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, OriginCaller, Balances,
+ Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, OriginCaller,
};
use pallet_unique_scheduler_v2::ScheduledEnsureOriginSuccess;
use up_common::types::AccountId;
runtime/common/scheduler.rsdiffbeforeafterboth--- a/runtime/common/scheduler.rs
+++ b/runtime/common/scheduler.rs
@@ -14,19 +14,16 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-use frame_support::{
- traits::NamedReservableCurrency,
- dispatch::{GetDispatchInfo, PostDispatchInfo, DispatchInfo},
-};
+use frame_support::dispatch::{GetDispatchInfo, PostDispatchInfo, DispatchInfo};
use sp_runtime::{
traits::{Dispatchable, Applyable, Member},
generic::Era,
transaction_validity::TransactionValidityError,
- DispatchErrorWithPostInfo, DispatchError,
+ DispatchErrorWithPostInfo,
};
use codec::Encode;
-use crate::{Runtime, RuntimeCall, RuntimeOrigin, Balances};
-use up_common::types::{AccountId, Balance};
+use crate::{Runtime, RuntimeCall, RuntimeOrigin};
+use up_common::types::AccountId;
use fp_self_contained::SelfContainedCall;
use pallet_unique_scheduler_v2::DispatchCall;
use pallet_transaction_payment::ChargeTransactionPayment;