Skip to content

Commit a5c56ea

Browse files
fix: first we try to decode data as a revert/require call
1 parent aa32c36 commit a5c56ea

File tree

1 file changed

+18
-18
lines changed

1 file changed

+18
-18
lines changed

Sources/Core/EthereumABI/ABIElements.swift

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ extension ABI.Element.Function {
264264
return Core.decodeInputData(rawData, methodEncoding: methodEncoding, inputs: inputs)
265265
}
266266

267-
/// Decodes data returned by a function call. Able to decode `revert("...")` calls.
267+
/// Decodes data returned by a function call. Able to decode `revert(message)`, `revert CustomError(...)` and `require(expression, message)` calls.
268268
/// - Parameter data: bytes returned by a function call.
269269
/// - Returns: a dictionary containing returned data mappend to indices and names of returned values if these are not `nil`.
270270
/// Return cases:
@@ -279,30 +279,15 @@ extension ABI.Element.Function {
279279
/// - `outputs` defined and `data` is empty;
280280
/// - `data` represent reverted transaction
281281
public func decodeReturnData(_ data: Data) -> [String: Any] {
282-
guard !outputs.isEmpty else {
283-
NSLog("Function doesn't have any output types to decode given data.")
284-
return ["_success": true]
285-
}
286-
287-
/// If data is empty and outputs are expected it is treated as a `requite(expression)` call with no message.
288-
/// In solidity `require(expression)` call, if `expresison` returns `false`, results in an empty response.
289-
if data.count == 0 && !outputs.isEmpty {
290-
return ["_success": false, "_failureReason": "Cannot decode empty data. \(outputs.count) outputs are expected: \(outputs.map { $0.type.abiRepresentation }). Was this a result of en empty `require(expression)` call?"]
291-
}
292-
293-
guard outputs.count * 32 <= data.count else {
294-
return ["_success": false, "_failureReason": "Bytes count must be at least \(outputs.count * 32). Given \(data.count). Decoding will fail."]
295-
}
296-
297282
/// How `require(expression, string)` return value is decomposed:
298283
/// - `08C379A0` function selector for Error(string);
299284
/// - next 32 bytes are the data offset;
300285
/// - next 32 bytes are the error message length;
301286
/// - the next N bytes, where N is the int value
302287
///
303288
/// Data offset must be present. Hexadecimal value of `0000...0020` is 32 in decimal. Reasoning for `BigInt(...) == 32`.
304-
if data[0..<4] == Data.fromHex("08C379A0"),
305-
data.bytes.count >= 100,
289+
if data.bytes.count >= 100,
290+
data[0..<4] == Data.fromHex("08C379A0"),
306291
BigInt(data[4..<36]) == 32,
307292
let messageLength = Int(Data(data[36..<68]).toHexString(), radix: 16),
308293
let message = String(bytes: data.bytes[68..<(68+messageLength)], encoding: .utf8) {
@@ -322,6 +307,21 @@ extension ABI.Element.Function {
322307
return returnArray
323308
}
324309

310+
guard !outputs.isEmpty else {
311+
NSLog("Function doesn't have any output types to decode given data.")
312+
return ["_success": true]
313+
}
314+
315+
/// If data is empty and outputs are expected it is treated as a `requite(expression)` call with no message.
316+
/// In solidity `require(expression)` call, if `expresison` returns `false`, results in an empty response.
317+
if data.count == 0 && !outputs.isEmpty {
318+
return ["_success": false, "_failureReason": "Cannot decode empty data. \(outputs.count) outputs are expected: \(outputs.map { $0.type.abiRepresentation }). Was this a result of en empty `require(expression)` call?"]
319+
}
320+
321+
guard outputs.count * 32 <= data.count else {
322+
return ["_success": false, "_failureReason": "Bytes count must be at least \(outputs.count * 32). Given \(data.count). Decoding will fail."]
323+
}
324+
325325
// TODO: need improvement - we should be able to tell which value failed to be decoded
326326
guard let values = ABIDecoder.decode(types: outputs, data: data) else {
327327
return ["_success": false, "_failureReason": "Failed to decode at least one value."]

0 commit comments

Comments
 (0)