@@ -34,6 +34,14 @@ export class TransactionDescription extends Description<TransactionDescription>
3434 readonly value : BigNumber ;
3535}
3636
37+ export class ErrorDescription extends Description < ErrorDescription > {
38+ readonly errorFragment : ErrorFragment ;
39+ readonly name : string ;
40+ readonly args : Result ;
41+ readonly signature : string ;
42+ readonly sighash : string ;
43+ }
44+
3745export class Indexed extends Description < Indexed > {
3846 readonly hash : string ;
3947 readonly _isIndexed : boolean ;
@@ -283,12 +291,20 @@ export class Interface {
283291 }
284292
285293 // Get the sighash (the bytes4 selector) used by Solidity to identify a function
286- getSighash ( functionFragment : FunctionFragment | string ) : string {
287- if ( typeof ( functionFragment ) === "string" ) {
288- functionFragment = this . getFunction ( functionFragment ) ;
294+ getSighash ( fragment : ErrorFragment | FunctionFragment | string ) : string {
295+ if ( typeof ( fragment ) === "string" ) {
296+ try {
297+ fragment = this . getFunction ( fragment ) ;
298+ } catch ( error ) {
299+ try {
300+ fragment = this . getError ( < string > fragment ) ;
301+ } catch ( _ ) {
302+ throw error ;
303+ }
304+ }
289305 }
290306
291- return getStatic < ( f : FunctionFragment ) => string > ( this . constructor , "getSighash" ) ( functionFragment ) ;
307+ return getStatic < ( f : ErrorFragment | FunctionFragment ) => string > ( this . constructor , "getSighash" ) ( fragment ) ;
292308 }
293309
294310 // Get the topic (the bytes32 hash) used by Solidity to identify an event
@@ -313,6 +329,31 @@ export class Interface {
313329 return this . _encodeParams ( this . deploy . inputs , values || [ ] ) ;
314330 }
315331
332+ decodeErrorData ( fragment : ErrorFragment | string , data : BytesLike ) : Result {
333+ if ( typeof ( fragment ) === "string" ) {
334+ fragment = this . getError ( fragment ) ;
335+ }
336+
337+ const bytes = arrayify ( data ) ;
338+
339+ if ( hexlify ( bytes . slice ( 0 , 4 ) ) !== this . getSighash ( fragment ) ) {
340+ logger . throwArgumentError ( `data signature does not match error ${ fragment . name } .` , "data" , hexlify ( bytes ) ) ;
341+ }
342+
343+ return this . _decodeParams ( fragment . inputs , bytes . slice ( 4 ) ) ;
344+ }
345+
346+ encodeErrorData ( fragment : ErrorFragment | string , values ?: ReadonlyArray < any > ) : string {
347+ if ( typeof ( fragment ) === "string" ) {
348+ fragment = this . getError ( fragment ) ;
349+ }
350+
351+ return hexlify ( concat ( [
352+ this . getSighash ( fragment ) ,
353+ this . _encodeParams ( fragment . inputs , values || [ ] )
354+ ] ) ) ;
355+ }
356+
316357 // Decode the data for a function call (e.g. tx.data)
317358 decodeFunctionData ( functionFragment : FunctionFragment | string , data : BytesLike ) : Result {
318359 if ( typeof ( functionFragment ) === "string" ) {
@@ -627,6 +668,21 @@ export class Interface {
627668 } ) ;
628669 }
629670
671+ parseError ( data : BytesLike ) : ErrorDescription {
672+ const hexData = hexlify ( data ) ;
673+ let fragment = this . getError ( hexData . substring ( 0 , 10 ) . toLowerCase ( ) )
674+
675+ if ( ! fragment ) { return null ; }
676+
677+ return new ErrorDescription ( {
678+ args : this . _abiCoder . decode ( fragment . inputs , "0x" + hexData . substring ( 10 ) ) ,
679+ errorFragment : fragment ,
680+ name : fragment . name ,
681+ signature : fragment . format ( ) ,
682+ sighash : this . getSighash ( fragment ) ,
683+ } ) ;
684+ }
685+
630686
631687 /*
632688 static from(value: Array<Fragment | string | JsonAbi> | string | Interface) {
0 commit comments