@@ -40,6 +40,7 @@ use core::{
4040} ;
4141use parity_scale_codec:: { self as codec, Decode , Encode , MaxEncodedLen } ;
4242use scale_info:: TypeInfo ;
43+ use bounded_collections:: { BoundedVec , ConstU32 } ;
4344
4445/// A general identifier for an instance of a non-fungible asset class.
4546#[ derive(
@@ -506,9 +507,8 @@ impl TryFrom<OldMultiAsset> for MultiAsset {
506507#[ cfg_attr( feature = "std" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
507508pub struct MultiAssets ( Vec < MultiAsset > ) ;
508509
509- /// Maximum number of items we expect in a single `MultiAssets` value. Note this is not (yet)
510- /// enforced, and just serves to provide a sensible `max_encoded_len` for `MultiAssets`.
511- const MAX_ITEMS_IN_MULTIASSETS : usize = 20 ;
510+ /// Maximum number of items in a single `MultiAssets` value that can be decoded.
511+ pub const MAX_ITEMS_IN_MULTIASSETS : usize = 20 ;
512512
513513impl MaxEncodedLen for MultiAssets {
514514 fn max_encoded_len ( ) -> usize {
@@ -517,8 +517,9 @@ impl MaxEncodedLen for MultiAssets {
517517}
518518
519519impl Decode for MultiAssets {
520- fn decode < I : codec:: Input > ( input : & mut I ) -> Result < Self , parity_scale_codec:: Error > {
521- Self :: from_sorted_and_deduplicated ( Vec :: < MultiAsset > :: decode ( input) ?)
520+ fn decode < I : codec:: Input > ( input : & mut I ) -> Result < Self , codec:: Error > {
521+ let bounded_instructions = BoundedVec :: < MultiAsset , ConstU32 < { MAX_ITEMS_IN_MULTIASSETS as u32 } > > :: decode ( input) ?;
522+ Self :: from_sorted_and_deduplicated ( bounded_instructions. into_inner ( ) )
522523 . map_err ( |( ) | "Out of order" . into ( ) )
523524 }
524525}
@@ -974,4 +975,31 @@ mod tests {
974975 let r = MultiAssets :: from_sorted_and_deduplicated ( mixed_bad) ;
975976 assert ! ( r. is_err( ) ) ;
976977 }
978+
979+ #[ test]
980+ fn decoding_respects_limit ( ) {
981+ use super :: * ;
982+
983+ // Having lots of one asset will work since they are deduplicated
984+ let lots_of_one_asset: MultiAssets =
985+ vec ! [ ( GeneralIndex ( 1 ) , 1u128 ) . into( ) ; MAX_ITEMS_IN_MULTIASSETS + 1 ] . into ( ) ;
986+ let encoded = lots_of_one_asset. encode ( ) ;
987+ assert ! ( MultiAssets :: decode( & mut & encoded[ ..] ) . is_ok( ) ) ;
988+
989+ // Fewer assets than the limit works
990+ let mut few_assets: MultiAssets = Vec :: new ( ) . into ( ) ;
991+ for i in 0 ..MAX_ITEMS_IN_MULTIASSETS {
992+ few_assets. push ( ( GeneralIndex ( i as u128 ) , 1u128 ) . into ( ) ) ;
993+ }
994+ let encoded = few_assets. encode ( ) ;
995+ assert ! ( MultiAssets :: decode( & mut & encoded[ ..] ) . is_ok( ) ) ;
996+
997+ // Having lots of different assets will not work
998+ let mut too_many_different_assets: MultiAssets = Vec :: new ( ) . into ( ) ;
999+ for i in 0 ..MAX_ITEMS_IN_MULTIASSETS + 1 {
1000+ too_many_different_assets. push ( ( GeneralIndex ( i as u128 ) , 1u128 ) . into ( ) ) ;
1001+ }
1002+ let encoded = too_many_different_assets. encode ( ) ;
1003+ assert ! ( MultiAssets :: decode( & mut & encoded[ ..] ) . is_err( ) ) ;
1004+ }
9771005}
0 commit comments