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::{46 weights::WeightInfo, Config, SelfWeightOf, NftTransferBasket, FungibleTransferBasket,47 ReFungibleTransferBasket, NftApproveBasket, FungibleApproveBasket, RefungibleApproveBasket,48};4950use alloc::format;51use sp_std::vec::Vec;5253/// See [`CollectionHelpersCall`]54pub struct EvmCollectionHelpers<T: Config>(SubstrateRecorder<T>);55impl<T: Config> WithRecorder<T> for EvmCollectionHelpers<T> {56 fn recorder(&self) -> &SubstrateRecorder<T> {57 &self.058 }5960 fn into_recorder(self) -> SubstrateRecorder<T> {61 self.062 }63}6465fn convert_data<T: Config>(66 caller: caller,67 name: string,68 description: string,69 token_prefix: string,70) -> Result<(71 T::CrossAccountId,72 CollectionName,73 CollectionDescription,74 CollectionTokenPrefix,75)> {76 let caller = T::CrossAccountId::from_eth(caller);77 let name = name78 .encode_utf16()79 .collect::<Vec<u16>>()80 .try_into()81 .map_err(|_| error_field_too_long(stringify!(name), CollectionName::bound()))?;82 let description = description83 .encode_utf16()84 .collect::<Vec<u16>>()85 .try_into()86 .map_err(|_| {87 error_field_too_long(stringify!(description), CollectionDescription::bound())88 })?;89 let token_prefix = token_prefix.into_bytes().try_into().map_err(|_| {90 error_field_too_long(stringify!(token_prefix), CollectionTokenPrefix::bound())91 })?;92 Ok((caller, name, description, token_prefix))93}9495#[inline(always)]96fn create_collection_internal<T: Config>(97 caller: caller,98 value: value,99 name: string,100 collection_mode: CollectionMode,101 description: string,102 token_prefix: string,103) -> Result<address> {104 let (caller, name, description, token_prefix) =105 convert_data::<T>(caller, name, description, token_prefix)?;106 let data = CreateCollectionData {107 name,108 mode: collection_mode,109 description,110 token_prefix,111 ..Default::default()112 };113 check_sent_amount_equals_collection_creation_price::<T>(value)?;114 let collection_helpers_address =115 T::CrossAccountId::from_eth(<T as pallet_common::Config>::ContractAddress::get());116117 let collection_id = T::CollectionDispatch::create(118 caller.clone(),119 collection_helpers_address,120 data,121 Default::default(),122 )123 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;124 let address = pallet_common::eth::collection_id_to_address(collection_id);125 Ok(address)126}127128fn check_sent_amount_equals_collection_creation_price<T: Config>(value: value) -> Result<()> {129 let value = value.as_u128();130 let creation_price: u128 = T::CollectionCreationPrice::get()131 .try_into()132 .map_err(|_| ()) // workaround for `expect` requiring `Debug` trait133 .expect("Collection creation price should be convertible to u128");134 if value != creation_price {135 return Err(format!(136 "Sent amount not equals to collection creation price ({0})",137 creation_price138 )139 .into());140 }141 Ok(())142}143144/// @title Contract, which allows users to operate with collections145#[solidity_interface(name = CollectionHelpers, events(CollectionHelpersEvents))]146impl<T> EvmCollectionHelpers<T>147where148 T: Config + pallet_common::Config + pallet_nonfungible::Config + pallet_refungible::Config,149{150 /// Create an NFT collection151 /// @param name Name of the collection152 /// @param description Informative description of the collection153 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications154 /// @return address Address of the newly created collection155 #[weight(<SelfWeightOf<T>>::create_collection())]156 #[solidity(rename_selector = "createNFTCollection")]157 fn create_nft_collection(158 &mut self,159 caller: caller,160 value: value,161 name: string,162 description: string,163 token_prefix: string,164 ) -> Result<address> {165 let (caller, name, description, token_prefix) =166 convert_data::<T>(caller, name, description, token_prefix)?;167 let data = CreateCollectionData {168 name,169 mode: CollectionMode::NFT,170 description,171 token_prefix,172 ..Default::default()173 };174 check_sent_amount_equals_collection_creation_price::<T>(value)?;175 let collection_helpers_address =176 T::CrossAccountId::from_eth(<T as pallet_common::Config>::ContractAddress::get());177 let collection_id = T::CollectionDispatch::create(178 caller,179 collection_helpers_address,180 data,181 Default::default(),182 )183 .map_err(dispatch_to_evm::<T>)?;184185 let address = pallet_common::eth::collection_id_to_address(collection_id);186 Ok(address)187 }188 /// Create an NFT collection189 /// @param name Name of the collection190 /// @param description Informative description of the collection191 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications192 /// @return address Address of the newly created collection193 #[weight(<SelfWeightOf<T>>::create_collection())]194 #[deprecated(note = "mathod was renamed to `create_nft_collection`, prefer it instead")]195 #[solidity(hide)]196 fn create_nonfungible_collection(197 &mut self,198 caller: caller,199 value: value,200 name: string,201 description: string,202 token_prefix: string,203 ) -> Result<address> {204 create_collection_internal::<T>(205 caller,206 value,207 name,208 CollectionMode::NFT,209 description,210 token_prefix,211 )212 }213214 #[weight(<SelfWeightOf<T>>::create_collection())]215 #[solidity(rename_selector = "createRFTCollection")]216 fn create_rft_collection(217 &mut self,218 caller: caller,219 value: value,220 name: string,221 description: string,222 token_prefix: string,223 ) -> Result<address> {224 create_collection_internal::<T>(225 caller,226 value,227 name,228 CollectionMode::ReFungible,229 description,230 token_prefix,231 )232 }233234 #[weight(<SelfWeightOf<T>>::create_collection())]235 #[solidity(rename_selector = "createFTCollection")]236 fn create_fungible_collection(237 &mut self,238 caller: caller,239 value: value,240 name: string,241 decimals: uint8,242 description: string,243 token_prefix: string,244 ) -> Result<address> {245 create_collection_internal::<T>(246 caller,247 value,248 name,249 CollectionMode::Fungible(decimals),250 description,251 token_prefix,252 )253 }254255 #[solidity(rename_selector = "makeCollectionERC721MetadataCompatible")]256 fn make_collection_metadata_compatible(257 &mut self,258 caller: caller,259 collection: address,260 base_uri: string,261 ) -> Result<()> {262 let caller = T::CrossAccountId::from_eth(caller);263 let collection =264 pallet_common::eth::map_eth_to_id(&collection).ok_or("not a collection address")?;265 let mut collection =266 <crate::CollectionHandle<T>>::new(collection).ok_or("collection not found")?;267268 if !matches!(269 collection.mode,270 CollectionMode::NFT | CollectionMode::ReFungible271 ) {272 return Err("target collection should be either NFT or Refungible".into());273 }274275 self.recorder().consume_sstore()?;276 collection277 .check_is_owner_or_admin(&caller)278 .map_err(dispatch_to_evm::<T>)?;279280 if collection.flags.erc721metadata {281 return Err("target collection is already Erc721Metadata compatible".into());282 }283 collection.flags.erc721metadata = true;284285 let all_permissions = <pallet_common::CollectionPropertyPermissions<T>>::get(collection.id);286 if all_permissions.get(&key::url()).is_none() {287 self.recorder().consume_sstore()?;288 <PalletCommon<T>>::set_property_permission(289 &collection,290 &caller,291 up_data_structs::PropertyKeyPermission {292 key: key::url(),293 permission: up_data_structs::PropertyPermission {294 mutable: true,295 collection_admin: true,296 token_owner: false,297 },298 },299 )300 .map_err(dispatch_to_evm::<T>)?;301 }302 if all_permissions.get(&key::suffix()).is_none() {303 self.recorder().consume_sstore()?;304 <PalletCommon<T>>::set_property_permission(305 &collection,306 &caller,307 up_data_structs::PropertyKeyPermission {308 key: key::suffix(),309 permission: up_data_structs::PropertyPermission {310 mutable: true,311 collection_admin: true,312 token_owner: false,313 },314 },315 )316 .map_err(dispatch_to_evm::<T>)?;317 }318319 let all_properties = <pallet_common::CollectionProperties<T>>::get(collection.id);320 if all_properties.get(&key::base_uri()).is_none() && !base_uri.is_empty() {321 self.recorder().consume_sstore()?;322 <PalletCommon<T>>::set_collection_properties(323 &collection,324 &caller,325 vec![up_data_structs::Property {326 key: key::base_uri(),327 value: base_uri328 .into_bytes()329 .try_into()330 .map_err(|_| "base uri is too large")?,331 }],332 )333 .map_err(dispatch_to_evm::<T>)?;334 }335336 self.recorder().consume_sstore()?;337 collection.save().map_err(dispatch_to_evm::<T>)?;338339 Ok(())340 }341342 #[weight(<SelfWeightOf<T>>::destroy_collection())]343 fn destroy_collection(&mut self, caller: caller, collection_address: address) -> Result<void> {344 let caller = T::CrossAccountId::from_eth(caller);345346 let collection_id = pallet_common::eth::map_eth_to_id(&collection_address)347 .ok_or("Invalid collection address format")?;348 <Pallet<T>>::destroy_collection_internal(caller, collection_id)349 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)350 }351352 /// Check if a collection exists353 /// @param collectionAddress Address of the collection in question354 /// @return bool Does the collection exist?355 fn is_collection_exist(&self, _caller: caller, collection_address: address) -> Result<bool> {356 if let Some(id) = pallet_common::eth::map_eth_to_id(&collection_address) {357 let collection_id = id;358 return Ok(<CollectionById<T>>::contains_key(collection_id));359 }360361 Ok(false)362 }363364 fn collection_creation_fee(&self) -> Result<value> {365 let price: u128 = T::CollectionCreationPrice::get()366 .try_into()367 .map_err(|_| ()) // workaround for `expect` requiring `Debug` trait368 .expect("Collection creation price should be convertible to u128");369 Ok(price.into())370 }371}372373/// Implements [`OnMethodCall`], which delegates call to [`EvmCollectionHelpers`]374pub struct CollectionHelpersOnMethodCall<T: Config>(PhantomData<*const T>);375impl<T: Config + pallet_nonfungible::Config + pallet_refungible::Config> OnMethodCall<T>376 for CollectionHelpersOnMethodCall<T>377{378 fn is_reserved(contract: &sp_core::H160) -> bool {379 contract == &T::ContractAddress::get()380 }381382 fn is_used(contract: &sp_core::H160) -> bool {383 contract == &T::ContractAddress::get()384 }385386 fn call(handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {387 if handle.code_address() != T::ContractAddress::get() {388 return None;389 }390391 let helpers =392 EvmCollectionHelpers::<T>(SubstrateRecorder::<T>::new(handle.remaining_gas()));393 pallet_evm_coder_substrate::call(handle, helpers)394 }395396 fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {397 (contract == &T::ContractAddress::get())398 .then(|| include_bytes!("./stubs/CollectionHelpers.raw").to_vec())399 }400}401402generate_stubgen!(collection_helper_impl, CollectionHelpersCall<()>, true);403generate_stubgen!(collection_helper_iface, CollectionHelpersCall<()>, false);404405fn error_field_too_long(feild: &str, bound: usize) -> Error {406 Error::Revert(format!("{} is too long. Max length is {}.", feild, bound))407}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;