Skip to content

Commit

Permalink
refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
rommex committed May 15, 2024
1 parent 712b7a1 commit 65ae5c7
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,18 @@ public struct EIP712Domain: Codable {

/// A struct represents EIP712 TypedData
public struct EIP712TypedData: Codable {
public let types: [String: [EIP712Type]]
public let declaredTypes: DeclaredTypes
public let primaryType: String
public let domain: JSON
public let message: JSON

public struct DeclaredTypes: Codable {
private let types: [String: [EIP712Type]]

func getEnclosedTypes(of typeName: String) -> [EIP712Type]? {
types[typeName]
}
}
}

struct Crypto {
Expand All @@ -50,22 +58,22 @@ extension EIP712TypedData {
}

private func hashStruct(_ data: JSON, type: String) -> Data {
return Crypto.hash(typeHash(type) + encodeData(data: data, type: type))
return Crypto.hash(typeHash(type) + encodeData(data: data, typeName: type))
}

/// Sign-able hash for an `EIP712TypedData`
public var signHash: Data {
let data = Data([0x19, 0x01]) +
Crypto.hash(encodeData(data: domain, type: "EIP712Domain")) +
Crypto.hash(encodeData(data: message, type: primaryType))
Crypto.hash(encodeData(data: domain, typeName: "EIP712Domain")) +
Crypto.hash(encodeData(data: message, typeName: primaryType))
return Crypto.hash(data)
}

/// Recursively finds all the dependencies of a type
func findDependencies(primaryType: String, dependencies: Set<String> = Set<String>()) -> Set<String> {
var found = dependencies
guard !found.contains(primaryType),
let primaryTypes = types[primaryType] else {
let primaryTypes = declaredTypes.getEnclosedTypes(of: primaryType) else {
return found
}
found.insert(primaryType)
Expand All @@ -82,7 +90,8 @@ extension EIP712TypedData {
depSet.remove(primaryType)
let sorted = [primaryType] + Array(depSet).sorted()
let encoded = sorted.map { type in
let param = types[type]!.map { "\($0.type) \($0.name)" }.joined(separator: ",")
let subTypes = declaredTypes.getEnclosedTypes(of: type)!
let param = subTypes.map { "\($0.type) \($0.name)" }.joined(separator: ",")
return "\(type)(\(param))"
}.joined()
return encoded.data(using: .utf8) ?? Data()
Expand All @@ -91,18 +100,19 @@ extension EIP712TypedData {
/// Encode an instance of struct
///
/// Implemented with `ABIEncoder` and `ABIValue`
public func encodeData(data: JSON, type: String) -> Data {
public func encodeData(data: JSON, typeName: String) -> Data {
let encoder = ABIEncoder()
var values: [ABIValue] = []
do {
let typeHash = Crypto.hash(encodeType(primaryType: type))
let typeHash = Crypto.hash(encodeType(primaryType: typeName))
let typeHashValue = try ABIValue(typeHash, type: .bytes(32))
values.append(typeHashValue)
if let valueTypes = types[type] {
if let valueTypes = declaredTypes.getEnclosedTypes(of: typeName) {
try valueTypes.forEach { field in
if let _ = types[field.type.removeEndingBracketsIfAny],
let typeName = field.type.removeEndingBracketsIfAny
if let _ = declaredTypes.getEnclosedTypes(of: typeName),
let json = data[field.name] {
let nestEncoded = encodeData(data: json, type: field.type.removeEndingBracketsIfAny)
let nestEncoded = encodeData(data: json, typeName: field.type.removeEndingBracketsIfAny)
values.append(try ABIValue(Crypto.hash(nestEncoded), type: .bytes(32)))
} else if let value = makeABIValue(data: data[field.name], type: field.type.removeEndingBracketsIfAny) {
values.append(value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ class SignatureTests: XCTestCase {
let jsonTypedData = try JSONDecoder().decode(EIP712TypedData.self, from: jsonString.data(using: .utf8)!)
// swiftlint:disable:next line_length
let result = "432c2e85cd4fb1991e30556bafe6d78422c6eeb812929bc1d2d4c7053998a4099c0257114eb9399a2985f8e75dad7600c5d89fe3824ffa99ec1c3eb8bf3b0501bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000001"
let data = jsonTypedData.encodeData(data: jsonTypedData.message, type: jsonTypedData.primaryType)
let data = jsonTypedData.encodeData(data: jsonTypedData.message, typeName: jsonTypedData.primaryType)
XCTAssertEqual(data.hexString, result)
}

Expand Down Expand Up @@ -308,18 +308,18 @@ class SignatureTests: XCTestCase {
func testEncodeData() {
// swiftlint:disable:next line_length
let result = "a0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8"
let data = simpleTypedData.encodeData(data: simpleTypedData.message, type: simpleTypedData.primaryType)
let data = simpleTypedData.encodeData(data: simpleTypedData.message, typeName: simpleTypedData.primaryType)
XCTAssertEqual(data.hexString, result)
}

func testStructHash() {
let result = "c52c0ee5d84264471806290a3f2c4cecfc5490626bf912d01f240d7a274b371e"
let data = simpleTypedData.encodeData(data: simpleTypedData.message, type: simpleTypedData.primaryType)
let data = simpleTypedData.encodeData(data: simpleTypedData.message, typeName: simpleTypedData.primaryType)
XCTAssertEqual(Crypto.hash(data).hexString, result)

let result2 = "f2cee375fa42b42143804025fc449deafd50cc031ca257e0b194a650a912090f"
// let json = try! JSONDecoder().decode(JSON.self, from: try! JSONEncoder().encode(typedData.domain))
let data2 = simpleTypedData.encodeData(data: simpleTypedData.domain, type: "EIP712Domain")
let data2 = simpleTypedData.encodeData(data: simpleTypedData.domain, typeName: "EIP712Domain")
XCTAssertEqual(Crypto.hash(data2).hexString, result2)
}

Expand Down Expand Up @@ -359,7 +359,7 @@ class SignatureTests: XCTestCase {

func testElementary() {
// SDK's encodeData is typeHash + encoded data
let encodeDataFromSDK = simpleTypedDataWithArray.encodeData(data: simpleTypedDataWithArray.message, type: "Mail")
let encodeDataFromSDK = simpleTypedDataWithArray.encodeData(data: simpleTypedDataWithArray.message, typeName: "Mail")

// let encodedFrom = Crypto.hash("Cow".data(using: .utf8)!) + Crypto.hash(
//
Expand Down

0 comments on commit 65ae5c7

Please sign in to comment.