@@ -36,6 +36,7 @@ use sp_std::{mem, result};
3636/// denoting that funds have been created without any equal and opposite
3737/// accounting.
3838#[ must_use]
39+ #[ derive( Debug ) ]
3940pub struct PositiveImbalance < T : Trait > {
4041 amount : T :: Balance ,
4142 asset_id : T :: AssetId ,
@@ -52,6 +53,7 @@ impl<T: Trait> PositiveImbalance<T> {
5253/// denoting that funds have been destroyed without any equal and opposite
5354/// accounting.
5455#[ must_use]
56+ #[ derive( Debug ) ]
5557pub struct NegativeImbalance < T : Trait > {
5658 amount : T :: Balance ,
5759 asset_id : T :: AssetId ,
@@ -77,7 +79,7 @@ impl<T: Trait> Imbalance<T::Balance> for PositiveImbalance<T> {
7779 Self :: new ( Zero :: zero ( ) , Zero :: zero ( ) )
7880 }
7981 fn drop_zero ( self ) -> result:: Result < ( ) , Self > {
80- if self . amount . is_zero ( ) {
82+ if self . amount . is_zero ( ) || self . asset_id . is_zero ( ) {
8183 Ok ( ( ) )
8284 } else {
8385 Err ( self )
@@ -130,7 +132,7 @@ impl<T: Trait> Imbalance<T::Balance> for NegativeImbalance<T> {
130132 Self :: new ( Zero :: zero ( ) , Zero :: zero ( ) )
131133 }
132134 fn drop_zero ( self ) -> result:: Result < ( ) , Self > {
133- if self . amount . is_zero ( ) {
135+ if self . amount . is_zero ( ) || self . asset_id . is_zero ( ) {
134136 Ok ( ( ) )
135137 } else {
136138 Err ( self )
@@ -185,41 +187,78 @@ impl<T: Trait> Drop for NegativeImbalance<T> {
185187}
186188
187189/// The result of an offset operation
190+ #[ derive( Debug ) ]
188191pub enum OffsetResult < T : Trait , I : Imbalance < T :: Balance > > {
189192 Imbalance ( I ) ,
190193 Opposite ( I :: Opposite ) ,
191194}
192195
196+ #[ derive( Debug , PartialEq , Eq ) ]
197+ pub enum Error {
198+ /// The operation cannot occur on imbalances with different asset IDs
199+ DifferentAssetIds ,
200+ /// The operation cannot occur when asset id is 0 and amount is not 0
201+ ZeroIdWithNonZeroAmount ,
202+ }
203+
193204/// Provides a safe API around imbalances with asset ID awareness
194205pub trait CheckedImbalance < T : Trait > : Imbalance < T :: Balance > {
195206 /// Get the imbalance asset ID
196207 fn asset_id ( & self ) -> T :: AssetId ;
197208 /// Get the imbalance amount
198209 fn amount ( & self ) -> T :: Balance ;
210+ /// Set the imbalance asset ID
211+ fn set_asset_id ( & mut self , new_asset_id : T :: AssetId ) ;
199212 /// Offset with asset ID safety checks
200- fn checked_offset ( self , other : Self :: Opposite ) -> result:: Result < OffsetResult < T , Self > , ( ) >
213+ fn checked_offset ( self , other : Self :: Opposite ) -> result:: Result < OffsetResult < T , Self > , Error >
201214 where
202215 Self :: Opposite : CheckedImbalance < T > ,
203216 {
217+ if other. asset_id ( ) . is_zero ( ) {
218+ return Ok ( OffsetResult :: Imbalance ( self ) )
219+ }
220+ if self . asset_id ( ) . is_zero ( ) && !self . amount ( ) . is_zero ( ) {
221+ return Err ( Error :: ZeroIdWithNonZeroAmount ) ;
222+ }
204223 if self . asset_id ( ) != other. asset_id ( ) {
205- return Err ( ( ) ) ;
224+ return Err ( Error :: DifferentAssetIds ) ;
206225 }
207226 match self . offset ( other) {
208227 Ok ( i) => Ok ( OffsetResult :: Imbalance ( i) ) ,
209228 Err ( i) => Ok ( OffsetResult :: Opposite ( i) ) ,
210229 }
211230 }
212231 /// Subsume with asset ID safety checks
213- fn checked_subsume ( & mut self , other : Self ) -> result:: Result < ( ) , ( ) > {
232+ fn checked_subsume ( & mut self , other : Self ) -> result:: Result < ( ) , Error > {
233+ if other. asset_id ( ) . is_zero ( ) {
234+ // noop, rhs is 0
235+ return Ok ( ( ) ) ;
236+ }
237+ if self . asset_id ( ) . is_zero ( ) && !self . amount ( ) . is_zero ( ) {
238+ return Err ( Error :: ZeroIdWithNonZeroAmount ) ;
239+ }
240+ if self . asset_id ( ) . is_zero ( ) {
241+ self . set_asset_id ( other. asset_id ( ) ) ;
242+ }
214243 if self . asset_id ( ) != other. asset_id ( ) {
215- return Err ( ( ) ) ;
244+ return Err ( Error :: DifferentAssetIds ) ;
216245 }
217246 Ok ( self . subsume ( other) )
218247 }
219248 /// Merge with asset ID safety checks
220- fn checked_merge ( self , other : Self ) -> result:: Result < Self , ( ) > {
249+ fn checked_merge ( mut self , other : Self ) -> result:: Result < Self , Error > {
250+ if other. asset_id ( ) . is_zero ( ) {
251+ // noop, rhs is 0
252+ return Ok ( self ) ;
253+ }
254+ if self . asset_id ( ) . is_zero ( ) && !self . amount ( ) . is_zero ( ) {
255+ return Err ( Error :: ZeroIdWithNonZeroAmount ) ;
256+ }
257+ if self . asset_id ( ) . is_zero ( ) {
258+ self . set_asset_id ( other. asset_id ( ) ) ;
259+ }
221260 if self . asset_id ( ) != other. asset_id ( ) {
222- return Err ( ( ) ) ;
261+ return Err ( Error :: DifferentAssetIds ) ;
223262 }
224263 Ok ( self . merge ( other) )
225264 }
@@ -232,6 +271,10 @@ impl<T: Trait> CheckedImbalance<T> for PositiveImbalance<T> {
232271 fn amount ( & self ) -> T :: Balance {
233272 self . amount
234273 }
274+ /// Set the imbalance asset ID
275+ fn set_asset_id ( & mut self , new_asset_id : T :: AssetId ) {
276+ self . asset_id = new_asset_id;
277+ }
235278}
236279
237280impl < T : Trait > CheckedImbalance < T > for NegativeImbalance < T > {
@@ -241,4 +284,8 @@ impl<T: Trait> CheckedImbalance<T> for NegativeImbalance<T> {
241284 fn amount ( & self ) -> T :: Balance {
242285 self . amount
243286 }
287+ /// Set the imbalance asset ID
288+ fn set_asset_id ( & mut self , new_asset_id : T :: AssetId ) {
289+ self . asset_id = new_asset_id;
290+ }
244291}
0 commit comments