135135
136136use sp_std:: { fmt:: Debug } ;
137137use sp_runtime:: { RuntimeDebug , traits:: {
138- Member , AtLeast32Bit , AtLeast32BitUnsigned , Zero , StaticLookup , One , Saturating , CheckedSub
138+ Member , AtLeast32Bit , AtLeast32BitUnsigned , Zero , StaticLookup , Saturating , CheckedSub
139139} } ;
140140use codec:: { Encode , Decode } ;
141141use frame_support:: { Parameter , decl_module, decl_event, decl_storage, decl_error, ensure,
@@ -203,7 +203,9 @@ pub struct AccountData<
203203decl_storage ! {
204204 trait Store for Module <T : Trait > as Assets {
205205 /// The number of units of assets held by any given account.
206- Account : map hasher( blake2_128_concat) ( T :: AssetId , T :: AccountId )
206+ Account : double_map
207+ hasher( blake2_128_concat) T :: AssetId ,
208+ hasher( blake2_128_concat) T :: AccountId
207209 => AccountData <T :: Balance >;
208210
209211 /// The next asset identifier up for grabs.
@@ -226,7 +228,7 @@ decl_event! {
226228 <T as Trait >:: Balance ,
227229 <T as Trait >:: AssetId ,
228230 {
229- /// Some assets were issued . \[asset_id, owner, total_supply \]
231+ /// Some asset class was created . \[asset_id, creator, owner \]
230232 Created ( AssetId , AccountId , AccountId ) ,
231233 /// Some assets were issued. \[asset_id, owner, total_supply\]
232234 Issued ( AssetId , AccountId , Balance ) ,
@@ -244,6 +246,8 @@ decl_event! {
244246 Frozen ( AssetId , AccountId ) ,
245247 /// Some account `who` was thawed. \[asset_id, who\]
246248 Thawed ( AssetId , AccountId ) ,
249+ /// An asset class was destroyed.
250+ Destroyed ( AssetId ) ,
247251 }
248252}
249253
@@ -261,6 +265,8 @@ decl_error! {
261265 Unknown ,
262266 /// The origin account is frozen.
263267 Frozen ,
268+ /// The asset ID is already taken.
269+ InUse ,
264270 }
265271}
266272
@@ -270,6 +276,8 @@ decl_module! {
270276
271277 fn deposit_event( ) = default ;
272278
279+ // TODO: destroy_asset
280+
273281 /// Issue a new class of fungible assets. There are, and will only ever be, `total`
274282 /// such assets and they'll all belong to the `origin` initially. It will have an
275283 /// identifier `AssetId` instance: this will be specified in the `Issued` event.
@@ -281,13 +289,11 @@ decl_module! {
281289 /// - 1 event.
282290 /// # </weight>
283291 #[ weight = 0 ]
284- fn create( origin, owner: <T :: Lookup as StaticLookup >:: Source ) {
292+ fn create( origin, # [ compact ] id : T :: AssetId , owner: <T :: Lookup as StaticLookup >:: Source ) {
285293 let origin = ensure_signed( origin) ?;
286294 let owner = T :: Lookup :: lookup( owner) ?;
287295
288- let id = Self :: next_asset_id( ) ;
289- NextAssetId :: <T >:: mutate( |id| * id += One :: one( ) ) ;
290-
296+ ensure!( !Details :: <T >:: contains_key( id) , Error :: <T >:: InUse ) ;
291297 Details :: <T >:: insert( id, AssetDetails {
292298 owner: owner. clone( ) ,
293299 issuer: owner. clone( ) ,
@@ -301,6 +307,20 @@ decl_module! {
301307 Self :: deposit_event( RawEvent :: Created ( id, origin, owner) ) ;
302308 }
303309
310+ #[ weight = 0 ]
311+ fn destroy( origin, #[ compact] id: T :: AssetId ) -> DispatchResult {
312+ let origin = ensure_signed( origin) ?;
313+
314+ Details :: <T >:: try_mutate_exists( id, |maybe_details| {
315+ let details = maybe_details. take( ) . ok_or( Error :: <T >:: Unknown ) ?;
316+ ensure!( details. owner == origin, Error :: <T >:: NoPermission ) ;
317+ * maybe_details = None ;
318+ Account :: <T >:: remove_prefix( & id) ;
319+ Self :: deposit_event( RawEvent :: Destroyed ( id) ) ;
320+ Ok ( ( ) )
321+ } )
322+ }
323+
304324 #[ weight = 0 ]
305325 fn mint( origin,
306326 #[ compact] id: T :: AssetId ,
@@ -314,7 +334,7 @@ decl_module! {
314334 let d = maybe_details. as_mut( ) . ok_or( Error :: <T >:: Unknown ) ?;
315335 ensure!( & origin == & d. issuer, Error :: <T >:: NoPermission ) ;
316336 d. supply = d. supply. saturating_add( amount) ;
317- Account :: <T >:: mutate( ( id, & beneficiary) , |t|
337+ Account :: <T >:: mutate( id, & beneficiary, |t|
318338 t. balance = t. balance. saturating_add( amount)
319339 ) ;
320340
@@ -337,24 +357,24 @@ decl_module! {
337357 target: <T :: Lookup as StaticLookup >:: Source ,
338358 #[ compact] amount: T :: Balance
339359 ) {
340- let origin = ( id , ensure_signed( origin) ?) ;
360+ let origin = ensure_signed( origin) ?;
341361 ensure!( !amount. is_zero( ) , Error :: <T >:: AmountZero ) ;
342362
343- let mut origin_account = Account :: <T >:: get( & origin) ;
363+ let mut origin_account = Account :: <T >:: get( id , & origin) ;
344364 ensure!( !origin_account. is_frozen, Error :: <T >:: Frozen ) ;
345365 origin_account. balance = origin_account. balance. checked_sub( & amount)
346366 . ok_or( Error :: <T >:: BalanceLow ) ?;
347367
348- let dest = ( id , T :: Lookup :: lookup( target) ?) ;
368+ let dest = T :: Lookup :: lookup( target) ?;
349369
350370 if origin_account. balance. is_zero( ) {
351- Account :: <T >:: remove( & origin) ;
371+ Account :: <T >:: remove( id , & origin) ;
352372 } else {
353- Account :: <T >:: insert( & origin, origin_account) ;
373+ Account :: <T >:: insert( id , & origin, origin_account) ;
354374 }
355- Account :: <T >:: mutate( & dest, |a| a. balance = a. balance. saturating_add( amount) ) ;
375+ Account :: <T >:: mutate( id , & dest, |a| a. balance = a. balance. saturating_add( amount) ) ;
356376
357- Self :: deposit_event( RawEvent :: Transferred ( id, origin. 1 , dest. 1 , amount) ) ;
377+ Self :: deposit_event( RawEvent :: Transferred ( id, origin, dest, amount) ) ;
358378 }
359379
360380 /// Destroy up to `amount` assets of `id` owned by `who`.
@@ -375,7 +395,7 @@ decl_module! {
375395 let d = maybe_details. as_mut( ) . ok_or( Error :: <T >:: Unknown ) ?;
376396 ensure!( & origin == & d. admin, Error :: <T >:: NoPermission ) ;
377397
378- let burned = Account :: <T >:: try_mutate_exists( ( id, & who) , |maybe_account| {
398+ let burned = Account :: <T >:: try_mutate_exists( id, & who, |maybe_account| {
379399 if let Some ( mut account) = maybe_account. take( ) {
380400 let burned = amount. min( account. balance) ;
381401 account. balance -= burned;
@@ -448,10 +468,10 @@ decl_module! {
448468 let d = Details :: <T >:: get( id) . ok_or( Error :: <T >:: Unknown ) ?;
449469 ensure!( & origin == & d. admin, Error :: <T >:: NoPermission ) ;
450470
451- let who = ( id , T :: Lookup :: lookup( who) ?) ;
452- Account :: <T >:: mutate( & who, |a| a. is_frozen = true ) ;
471+ let who = T :: Lookup :: lookup( who) ?;
472+ Account :: <T >:: mutate( id , & who, |a| a. is_frozen = true ) ;
453473
454- Self :: deposit_event( Event :: <T >:: Frozen ( id, who. 1 ) ) ;
474+ Self :: deposit_event( Event :: <T >:: Frozen ( id, who) ) ;
455475 }
456476
457477 #[ weight = 0 ]
@@ -461,10 +481,10 @@ decl_module! {
461481 let d = Details :: <T >:: get( id) . ok_or( Error :: <T >:: Unknown ) ?;
462482 ensure!( & origin == & d. admin, Error :: <T >:: NoPermission ) ;
463483
464- let who = ( id , T :: Lookup :: lookup( who) ?) ;
465- Account :: <T >:: mutate( & who, |a| a. is_frozen = false ) ;
484+ let who = T :: Lookup :: lookup( who) ?;
485+ Account :: <T >:: mutate( id , & who, |a| a. is_frozen = false ) ;
466486
467- Self :: deposit_event( Event :: <T >:: Thawed ( id, who. 1 ) ) ;
487+ Self :: deposit_event( Event :: <T >:: Thawed ( id, who) ) ;
468488 }
469489
470490 #[ weight = 0 ]
@@ -479,24 +499,24 @@ decl_module! {
479499 let d = Details :: <T >:: get( id) . ok_or( Error :: <T >:: Unknown ) ?;
480500 ensure!( & origin == & d. admin, Error :: <T >:: NoPermission ) ;
481501
482- let source = ( id , T :: Lookup :: lookup( source) ?) ;
483- let mut source_account = Account :: <T >:: get( & source) ;
502+ let source = T :: Lookup :: lookup( source) ?;
503+ let mut source_account = Account :: <T >:: get( id , & source) ;
484504 let amount = amount. min( source_account. balance) ;
485505
486506 ensure!( !amount. is_zero( ) , Error :: <T >:: AmountZero ) ;
487507
488- let dest = ( id , T :: Lookup :: lookup( dest) ?) ;
508+ let dest = T :: Lookup :: lookup( dest) ?;
489509
490510 source_account. balance -= amount;
491511 if source_account. balance. is_zero( ) {
492- Account :: <T >:: remove( & source) ;
512+ Account :: <T >:: remove( id , & source) ;
493513 } else {
494- Account :: <T >:: insert( & source, source_account) ;
514+ Account :: <T >:: insert( id , & source, source_account) ;
495515 }
496516
497- Account :: <T >:: mutate( & dest, |a| a. balance = a. balance. saturating_add( amount) ) ;
517+ Account :: <T >:: mutate( id , & dest, |a| a. balance = a. balance. saturating_add( amount) ) ;
498518
499- Self :: deposit_event( RawEvent :: ForceTransferred ( id, source. 1 , dest. 1 , amount) ) ;
519+ Self :: deposit_event( RawEvent :: ForceTransferred ( id, source, dest, amount) ) ;
500520 }
501521 }
502522}
@@ -507,7 +527,7 @@ impl<T: Trait> Module<T> {
507527
508528 /// Get the asset `id` balance of `who`.
509529 pub fn balance ( id : T :: AssetId , who : T :: AccountId ) -> T :: Balance {
510- Account :: < T > :: get ( ( id, who) ) . balance
530+ Account :: < T > :: get ( id, who) . balance
511531 }
512532
513533 /// Get the total supply of an asset `id`.
@@ -595,7 +615,7 @@ mod tests {
595615 #[ test]
596616 fn issuing_asset_units_to_issuer_should_work ( ) {
597617 new_test_ext ( ) . execute_with ( || {
598- assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 1 ) ) ;
618+ assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 0 , 1 ) ) ;
599619 assert_ok ! ( Assets :: mint( Origin :: signed( 1 ) , 0 , 1 , 100 ) ) ;
600620 assert_eq ! ( Assets :: balance( 0 , 1 ) , 100 ) ;
601621 } ) ;
@@ -604,7 +624,7 @@ mod tests {
604624 #[ test]
605625 fn querying_total_supply_should_work ( ) {
606626 new_test_ext ( ) . execute_with ( || {
607- assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 1 ) ) ;
627+ assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 0 , 1 ) ) ;
608628 assert_ok ! ( Assets :: mint( Origin :: signed( 1 ) , 0 , 1 , 100 ) ) ;
609629 assert_eq ! ( Assets :: balance( 0 , 1 ) , 100 ) ;
610630 assert_ok ! ( Assets :: transfer( Origin :: signed( 1 ) , 0 , 2 , 50 ) ) ;
@@ -622,7 +642,7 @@ mod tests {
622642 #[ test]
623643 fn transferring_amount_above_available_balance_should_work ( ) {
624644 new_test_ext ( ) . execute_with ( || {
625- assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 1 ) ) ;
645+ assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 0 , 1 ) ) ;
626646 assert_ok ! ( Assets :: mint( Origin :: signed( 1 ) , 0 , 1 , 100 ) ) ;
627647 assert_eq ! ( Assets :: balance( 0 , 1 ) , 100 ) ;
628648 assert_ok ! ( Assets :: transfer( Origin :: signed( 1 ) , 0 , 2 , 50 ) ) ;
@@ -634,7 +654,7 @@ mod tests {
634654 #[ test]
635655 fn transferring_amount_more_than_available_balance_should_not_work ( ) {
636656 new_test_ext ( ) . execute_with ( || {
637- assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 1 ) ) ;
657+ assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 0 , 1 ) ) ;
638658 assert_ok ! ( Assets :: mint( Origin :: signed( 1 ) , 0 , 1 , 100 ) ) ;
639659 assert_eq ! ( Assets :: balance( 0 , 1 ) , 100 ) ;
640660 assert_ok ! ( Assets :: transfer( Origin :: signed( 1 ) , 0 , 2 , 50 ) ) ;
@@ -649,7 +669,7 @@ mod tests {
649669 #[ test]
650670 fn transferring_less_than_one_unit_should_not_work ( ) {
651671 new_test_ext ( ) . execute_with ( || {
652- assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 1 ) ) ;
672+ assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 0 , 1 ) ) ;
653673 assert_ok ! ( Assets :: mint( Origin :: signed( 1 ) , 0 , 1 , 100 ) ) ;
654674 assert_eq ! ( Assets :: balance( 0 , 1 ) , 100 ) ;
655675 assert_noop ! ( Assets :: transfer( Origin :: signed( 1 ) , 0 , 2 , 0 ) , Error :: <Test >:: AmountZero ) ;
@@ -659,7 +679,7 @@ mod tests {
659679 #[ test]
660680 fn transferring_more_units_than_total_supply_should_not_work ( ) {
661681 new_test_ext ( ) . execute_with ( || {
662- assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 1 ) ) ;
682+ assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 0 , 1 ) ) ;
663683 assert_ok ! ( Assets :: mint( Origin :: signed( 1 ) , 0 , 1 , 100 ) ) ;
664684 assert_eq ! ( Assets :: balance( 0 , 1 ) , 100 ) ;
665685 assert_noop ! ( Assets :: transfer( Origin :: signed( 1 ) , 0 , 2 , 101 ) , Error :: <Test >:: BalanceLow ) ;
@@ -669,7 +689,7 @@ mod tests {
669689 #[ test]
670690 fn destroying_asset_balance_with_positive_balance_should_work ( ) {
671691 new_test_ext ( ) . execute_with ( || {
672- assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 1 ) ) ;
692+ assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 0 , 1 ) ) ;
673693 assert_ok ! ( Assets :: mint( Origin :: signed( 1 ) , 0 , 1 , 100 ) ) ;
674694 assert_eq ! ( Assets :: balance( 0 , 1 ) , 100 ) ;
675695 assert_ok ! ( Assets :: burn( Origin :: signed( 1 ) , 0 , 1 , u64 :: max_value( ) ) ) ;
@@ -679,7 +699,7 @@ mod tests {
679699 #[ test]
680700 fn destroying_asset_balance_with_zero_balance_should_not_work ( ) {
681701 new_test_ext ( ) . execute_with ( || {
682- assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 1 ) ) ;
702+ assert_ok ! ( Assets :: create( Origin :: signed( 1 ) , 0 , 1 ) ) ;
683703 assert_ok ! ( Assets :: mint( Origin :: signed( 1 ) , 0 , 1 , 100 ) ) ;
684704 assert_eq ! ( Assets :: balance( 0 , 2 ) , 0 ) ;
685705 assert_noop ! ( Assets :: burn( Origin :: signed( 1 ) , 0 , 2 , u64 :: max_value( ) ) , Error :: <Test >:: BalanceZero ) ;
0 commit comments