Skip to content

Commit 6cc06db

Browse files
fix: parsing and encoding of "bytes"
1 parent bd1544d commit 6cc06db

File tree

2 files changed

+141
-5
lines changed

2 files changed

+141
-5
lines changed

Sources/web3swift/Utils/EIP/EIP712/EIP712Parser.swift

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,19 +225,26 @@ public struct EIP712TypedData {
225225
var encValues: [Any] = []
226226
if field.type == "string" {
227227
guard let value = value as? String else {
228-
throw Web3Error.processingError(desc: "EIP712Parser. Type metadata '\(field)' and actual value '\(String(describing: value))' type doesn't match. Cannot cast value to String.")
228+
throw Web3Error.processingError(desc: "EIP712Parser. Type metadata of '\(field)' and actual value '\(String(describing: value))' type doesn't match. Cannot cast value to String. Parent object type: \(type).")
229229
}
230230
encTypes.append(.bytes(length: 32))
231231
encValues.append(value.sha3(.keccak256).addHexPrefix())
232232
} else if field.type == "bytes"{
233-
guard let value = value as? Data else {
234-
throw Web3Error.processingError(desc: "EIP712Parser. Type metadata '\(field)' and actual value '\(String(describing: value))' type doesn't match. Cannot cast value to Data.")
233+
let _value: Data?
234+
if let value = value as? String,
235+
let data = Data.fromHex(value) {
236+
_value = data
237+
} else {
238+
_value = value as? Data
239+
}
240+
guard let value = _value else {
241+
throw Web3Error.processingError(desc: "EIP712Parser. Type metadata '\(field)' and actual value '\(String(describing: value))' type doesn't match. Cannot cast/parse value to Data. Parent object type: \(type).")
235242
}
236243
encTypes.append(.bytes(length: 32))
237244
encValues.append(value.sha3(.keccak256))
238245
} else if field.isArray {
239246
guard let values = value as? [AnyObject] else {
240-
throw Web3Error.processingError(desc: "EIP712Parser. Custom type metadata '\(field)' and actual value '\(String(describing: value))' type doesn't match. Cannot cast value to [AnyObject].")
247+
throw Web3Error.processingError(desc: "EIP712Parser. Custom type metadata '\(field)' and actual value '\(String(describing: value))' type doesn't match. Cannot cast value to [AnyObject]. Parent object type: \(type)")
241248
}
242249
encTypes.append(.bytes(length: 32))
243250
let subField = EIP712TypeProperty(name: field.name, type: field.coreType)
@@ -250,7 +257,7 @@ public struct EIP712TypedData {
250257
}
251258

252259
guard let encodedValue = ABIEncoder.encode(types: encodedSubTypes, values: encodedSubValues) else {
253-
throw Web3Error.processingError(desc: "EIP712Parser. Failed to encode an array of custom type. Field: '\(field)'; value: '\(String(describing: value))'.")
260+
throw Web3Error.processingError(desc: "EIP712Parser. Failed to encode an array of custom type. Field: '\(field)'; value: '\(String(describing: value))'. Parent object type: \(type)")
254261
}
255262

256263
encValues.append(encodedValue.sha3(.keccak256))

Tests/web3swiftTests/localTests/EIP712TypedDataPayloadTests.swift

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,4 +461,133 @@ class EIP712TypedDataPayloadTests: XCTestCase {
461461
let parsedPayload = try EIP712Parser.parse(rawPayload)
462462
try XCTAssertEqual(parsedPayload.signHash().toHexString(), "54140d99a864932cbc40fd8a2d1d1706c3923a79c183a3b151e929ac468064db")
463463
}
464+
465+
/// A test to check payload encoding, specifically parsing and encoding of fields with "bytes" type.
466+
/// Given raw payload was failing with the following error:
467+
/// ```
468+
/// EIP712Parser.
469+
/// Type metadata 'EIP712TypeProperty(name: "data", type: "bytes", coreType: "bytes", isArray: false)'
470+
/// and actual value
471+
/// 'Optional(0x000000000000000000000000e84a7676aae742770a179dd7431073429a88c7b8000000000000000000000000000000000000000000000000000000000000002c)'
472+
/// type doesn't match.
473+
/// Cannot cast value to Data.
474+
///
475+
/// ```
476+
func testEIP712BytesEncoding() throws {
477+
let rawPayload = """
478+
{
479+
"message":{
480+
"takeAsset":{
481+
"assetType":{
482+
"assetClass":"0xaaaebeba",
483+
"data":"0x"
484+
},
485+
"value":"2000000000000000000"
486+
},
487+
"data":"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000d6ffd79b52a587a0a9941a61f4e6cb0d386d54580000000000000000000000000000000000000000000000000000000000000064",
488+
"dataType":"0x23d235ef",
489+
"maker":"0xd0727e8a578de9dd19bced635b1aa43576e638bc",
490+
"taker":"0x0000000000000000000000000000000000000000",
491+
"salt":"0x8f9761e56ed73b34d0cb184a2c5530d86c355c63c1cde8db1e0d2557d93f10d7",
492+
"end":1703058225,
493+
"makeAsset":{
494+
"value":"1",
495+
"assetType":{
496+
"data":"0x000000000000000000000000e84a7676aae742770a179dd7431073429a88c7b8000000000000000000000000000000000000000000000000000000000000002c",
497+
"assetClass":"0x73ad2146"
498+
}
499+
},
500+
"start":0
501+
},
502+
"domain":{
503+
"verifyingContract":"0x02afbd43cad367fcb71305a2dfb9a3928218f0c1",
504+
"version":"2",
505+
"chainId":5,
506+
"name":"Exchange"
507+
},
508+
"primaryType":"Order",
509+
"types":{
510+
"Order":[
511+
{
512+
"type":"address",
513+
"name":"maker"
514+
},
515+
{
516+
"type":"Asset",
517+
"name":"makeAsset"
518+
},
519+
{
520+
"name":"taker",
521+
"type":"address"
522+
},
523+
{
524+
"name":"takeAsset",
525+
"type":"Asset"
526+
},
527+
{
528+
"name":"salt",
529+
"type":"uint256"
530+
},
531+
{
532+
"name":"start",
533+
"type":"uint256"
534+
},
535+
{
536+
"type":"uint256",
537+
"name":"end"
538+
},
539+
{
540+
"type":"bytes4",
541+
"name":"dataType"
542+
},
543+
{
544+
"type":"bytes",
545+
"name":"data"
546+
}
547+
],
548+
"EIP712Domain":[
549+
{
550+
"name":"name",
551+
"type":"string"
552+
},
553+
{
554+
"type":"string",
555+
"name":"version"
556+
},
557+
{
558+
"name":"chainId",
559+
"type":"uint256"
560+
},
561+
{
562+
"name":"verifyingContract",
563+
"type":"address"
564+
}
565+
],
566+
"Asset":[
567+
{
568+
"name":"assetType",
569+
"type":"AssetType"
570+
},
571+
{
572+
"type":"uint256",
573+
"name":"value"
574+
}
575+
],
576+
"AssetType":[
577+
{
578+
"type":"bytes4",
579+
"name":"assetClass"
580+
},
581+
{
582+
"name":"data",
583+
"type":"bytes"
584+
}
585+
]
586+
}
587+
}
588+
"""
589+
590+
let parsedPayload = try EIP712Parser.parse(rawPayload)
591+
try XCTAssertEqual(parsedPayload.signHash().toHexString(), "95625b9843950aa6cdd50c703e2bf0bdaa5ddeef9842d5839a81d927b7159637")
592+
}
464593
}

0 commit comments

Comments
 (0)