Skip to content

Commit 3e5da9f

Browse files
feat: decoding ABI with solidity error types
1 parent 5b45521 commit 3e5da9f

File tree

5 files changed

+78
-2
lines changed

5 files changed

+78
-2
lines changed

Sources/web3swift/EthereumABI/ABIElements.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public extension ABI {
4444
case fallback(Fallback)
4545
case event(Event)
4646
case receive(Receive)
47+
case error(EthError)
4748

4849
public enum StateMutability {
4950
case payable
@@ -152,6 +153,21 @@ public extension ABI {
152153
self.payable = payable
153154
}
154155
}
156+
/// Custom structured error type available since solidity 0.8.4
157+
public struct EthError {
158+
public let name: String
159+
public let inputs: [Input]
160+
161+
public struct Input {
162+
public let name: String
163+
public let type: ParameterType
164+
165+
public init(name: String, type: ParameterType) {
166+
self.name = name
167+
self.type = type
168+
}
169+
}
170+
}
155171
}
156172
}
157173

@@ -173,6 +189,8 @@ extension ABI.Element {
173189
return signature + data
174190
case .receive(_):
175191
return nil
192+
case .error(_):
193+
return nil
176194
}
177195
}
178196
}
@@ -249,6 +267,8 @@ extension ABI.Element {
249267
return returnArray
250268
case .receive(_):
251269
return nil
270+
case .error(_):
271+
return nil
252272
}
253273
}
254274

@@ -324,6 +344,8 @@ extension ABI.Element {
324344
return returnArray
325345
case .receive(_):
326346
return nil
347+
case .error(_):
348+
return nil
327349
}
328350
}
329351
}

Sources/web3swift/EthereumABI/ABIParsing.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ extension ABI {
3131
case fallback
3232
case event
3333
case receive
34+
case error
3435
}
3536

3637
}
@@ -62,6 +63,9 @@ fileprivate func parseToElement(from abiRecord: ABI.Record, type: ABI.ElementTyp
6263
case .receive:
6364
let receive = try parseReceive(abiRecord: abiRecord)
6465
return ABI.Element.receive(receive)
66+
case .error:
67+
let error = try parseError(abiRecord: abiRecord)
68+
return ABI.Element.error(error)
6569
}
6670

6771
}
@@ -142,6 +146,16 @@ fileprivate func parseReceive(abiRecord:ABI.Record) throws -> ABI.Element.Receiv
142146
return functionElement
143147
}
144148

149+
fileprivate func parseError(abiRecord:ABI.Record) throws -> ABI.Element.EthError {
150+
let inputs = try abiRecord.inputs?.map({ (input:ABI.Input) throws -> ABI.Element.EthError.Input in
151+
let nativeInput = try input.parseForError()
152+
return nativeInput
153+
})
154+
let abiInputs = inputs ?? []
155+
let name = abiRecord.name != nil ? abiRecord.name! : ""
156+
return ABI.Element.EthError(name: name, inputs: abiInputs)
157+
}
158+
145159
extension ABI.Input {
146160
func parse() throws -> ABI.Element.InOut {
147161
let name = self.name != nil ? self.name! : ""
@@ -172,12 +186,18 @@ extension ABI.Input {
172186
}
173187
}
174188

175-
func parseForEvent() throws -> ABI.Element.Event.Input{
189+
func parseForEvent() throws -> ABI.Element.Event.Input {
176190
let name = self.name != nil ? self.name! : ""
177191
let parameterType = try ABITypeParser.parseTypeString(self.type)
178192
let indexed = self.indexed == true
179193
return ABI.Element.Event.Input(name:name, type: parameterType, indexed: indexed)
180194
}
195+
196+
func parseForError() throws -> ABI.Element.EthError.Input {
197+
let name = self.name != nil ? self.name! : ""
198+
let parameterType = try ABITypeParser.parseTypeString(self.type)
199+
return ABI.Element.EthError.Input(name:name, type: parameterType)
200+
}
181201
}
182202

183203
extension ABI.Output {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//
2+
// web3swift_decodeSolidityErrorType.swift
3+
// Tests
4+
//
5+
// Created by JeneaVranceanu on 25/01/2022.
6+
// Copyright © 2022 web3swift. All rights reserved.
7+
//
8+
9+
import XCTest
10+
import web3swift
11+
12+
/// Since solidity 0.8.4 a new type was introduced called `error`.
13+
/// Contracts' ABI with this type were not decodable.
14+
class web3swift_decodeSolidityErrorType: XCTestCase {
15+
16+
func test_structuredErrorTypeDecoding() throws {
17+
let contractAbiWithErrorTypes = "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"disallowedAddress\",\"type\":\"address\"}],\"name\":\"NotAllowedAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"bytes4\",\"name\":\"disallowedFunction\",\"type\":\"bytes4\"}],\"name\":\"NotAllowedFunction\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"permission\",\"type\":\"string\"}],\"name\":\"NotAuthorised\",\"type\":\"error\"}]"
18+
let web3Instance = try Web3.new(URL.init(string: "http://127.0.0.1:8545")!)
19+
let contract = web3.web3contract(web3: web3Instance, abiString: contractAbiWithErrorTypes)
20+
assert(contract != nil)
21+
}
22+
}

web3swift.xcodeproj/project.pbxproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@
191191
5C03EADF274406410052C66D /* web3swift_AdvancedABIv2_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C03EACD274406400052C66D /* web3swift_AdvancedABIv2_Tests.swift */; };
192192
5C03EAE0274406410052C66D /* web3swift_transactions_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C03EACE274406410052C66D /* web3swift_transactions_Tests.swift */; };
193193
CB50A52827060BD600D7E39B /* web3swift_EIP712_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB50A52727060BD600D7E39B /* web3swift_EIP712_Tests.swift */; };
194+
D606A56B279F5D59003643ED /* web3swift_decodeSolidityErrorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D606A56A279F5D59003643ED /* web3swift_decodeSolidityErrorType.swift */; };
194195
E22A911F241ED71A00EC1021 /* browser.min.js in Resources */ = {isa = PBXBuildFile; fileRef = E22A911E241ED71A00EC1021 /* browser.min.js */; };
195196
E252E67F26B403F500717C16 /* web3swift_helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = E252E67E26B403F500717C16 /* web3swift_helpers.swift */; };
196197
E2B76710241ED479007EBFE3 /* browser.js in Resources */ = {isa = PBXBuildFile; fileRef = E2B7670F241ED479007EBFE3 /* browser.js */; };
@@ -405,11 +406,12 @@
405406
5C03EACC274406400052C66D /* web3swift_User_cases.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = web3swift_User_cases.swift; sourceTree = "<group>"; };
406407
5C03EACD274406400052C66D /* web3swift_AdvancedABIv2_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = web3swift_AdvancedABIv2_Tests.swift; sourceTree = "<group>"; };
407408
5C03EACE274406410052C66D /* web3swift_transactions_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = web3swift_transactions_Tests.swift; sourceTree = "<group>"; };
408-
5CDEF972275A74590004A2F2 /* web3swift.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = file; name = web3swift.xctestplan; path = Tests/web3swiftTests/web3swift.xctestplan; sourceTree = SOURCE_ROOT; };
409+
5CDEF972275A74590004A2F2 /* web3swift.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = web3swift.xctestplan; path = Tests/web3swiftTests/web3swift.xctestplan; sourceTree = SOURCE_ROOT; };
409410
5CDEF973275A74670004A2F2 /* LocalTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = LocalTests.xctestplan; sourceTree = "<group>"; };
410411
5CDEF974275A747B0004A2F2 /* RemoteTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = RemoteTests.xctestplan; sourceTree = "<group>"; };
411412
CB50A52727060BD600D7E39B /* web3swift_EIP712_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = web3swift_EIP712_Tests.swift; sourceTree = "<group>"; };
412413
CB50A52927060C5300D7E39B /* EIP712.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EIP712.swift; sourceTree = "<group>"; };
414+
D606A56A279F5D59003643ED /* web3swift_decodeSolidityErrorType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = web3swift_decodeSolidityErrorType.swift; sourceTree = "<group>"; };
413415
E22A911E241ED71A00EC1021 /* browser.min.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = browser.min.js; sourceTree = "<group>"; };
414416
E252E67E26B403F500717C16 /* web3swift_helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = web3swift_helpers.swift; sourceTree = "<group>"; };
415417
E2B7670F241ED479007EBFE3 /* browser.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = browser.js; sourceTree = "<group>"; };
@@ -1005,6 +1007,7 @@
10051007
5C03EACC274406400052C66D /* web3swift_User_cases.swift */,
10061008
E252E67E26B403F500717C16 /* web3swift_helpers.swift */,
10071009
5CDEF973275A74670004A2F2 /* LocalTests.xctestplan */,
1010+
D606A56A279F5D59003643ED /* web3swift_decodeSolidityErrorType.swift */,
10081011
);
10091012
path = local_tests;
10101013
sourceTree = "<group>";
@@ -1384,6 +1387,7 @@
13841387
5C03EACF274406410052C66D /* web3swift_helpers.swift in Sources */,
13851388
5C03EAD4274406410052C66D /* web3swift_numberFormattingUtil_Tests.swift in Sources */,
13861389
CB50A52827060BD600D7E39B /* web3swift_EIP712_Tests.swift in Sources */,
1390+
D606A56B279F5D59003643ED /* web3swift_decodeSolidityErrorType.swift in Sources */,
13871391
5C03EAE0274406410052C66D /* web3swift_transactions_Tests.swift in Sources */,
13881392
5C03EAD9274406410052C66D /* web3swift_keystores_Tests.swift in Sources */,
13891393
5C03EAD8274406410052C66D /* web3swift_Eventloop_Tests.swift in Sources */,
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>

0 commit comments

Comments
 (0)