Skip to content

Commit 5f38e99

Browse files
chore: minor reordering of the structures in EIP712.swift file; removed EIP712DomainHashable as it is redundant;
chore: removed multiple `private func keccak256` defined in EIP712.swift file. These were redundant. chore: `EIP712Domain` is now public as it's a required model for Gnosis Safe transaction. May be reused by other developers;
1 parent f061af2 commit 5f38e99

File tree

1 file changed

+55
-56
lines changed

1 file changed

+55
-56
lines changed

Sources/web3swift/Utils/EIP/EIP712.swift

Lines changed: 55 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,8 @@
1-
import BigInt
21
import CryptoSwift
32
import Foundation
3+
import BigInt
44
import Core
55

6-
// TODO: Refactor me
7-
8-
struct EIP712Domain: EIP712DomainHashable {
9-
let chainId: EIP712.UInt256?
10-
let verifyingContract: EIP712.Address
11-
}
12-
13-
protocol EIP712DomainHashable: EIP712Hashable {}
14-
15-
public struct SafeTx: EIP712Hashable {
16-
let to: EIP712.Address
17-
let value: EIP712.UInt256
18-
let data: EIP712.Bytes
19-
let operation: EIP712.UInt8
20-
let safeTxGas: EIP712.UInt256
21-
let baseGas: EIP712.UInt256
22-
let gasPrice: EIP712.UInt256
23-
let gasToken: EIP712.Address
24-
let refundReceiver: EIP712.Address
25-
let nonce: EIP712.UInt256
26-
27-
public init(to: EIP712.Address, value: EIP712.UInt256, data: EIP712.Bytes, operation: EIP712.UInt8, safeTxGas: EIP712.UInt256, baseGas: EIP712.UInt256, gasPrice: EIP712.UInt256, gasToken: EIP712.Address, refundReceiver: EIP712.Address, nonce: EIP712.UInt256) {
28-
self.to = to
29-
self.value = value
30-
self.data = data
31-
self.operation = operation
32-
self.safeTxGas = safeTxGas
33-
self.baseGas = baseGas
34-
self.gasPrice = gasPrice
35-
self.gasToken = gasToken
36-
self.refundReceiver = refundReceiver
37-
self.nonce = nonce
38-
}
39-
40-
}
41-
426
/// Protocol defines EIP712 struct encoding
437
public protocol EIP712Hashable {
448
var typehash: Data { get }
@@ -52,6 +16,15 @@ public class EIP712 {
5216
public typealias Bytes = Data
5317
}
5418

19+
public struct EIP712Domain: EIP712Hashable {
20+
public let chainId: EIP712.UInt256?
21+
public let verifyingContract: EIP712.Address
22+
public init(chainId: EIP712.UInt256?, verifyingContract: EIP712.Address) {
23+
self.chainId = chainId
24+
self.verifyingContract = verifyingContract
25+
}
26+
}
27+
5528
public extension EIP712.Address {
5629
static var zero: Self {
5730
EthereumAddress(Data(count: 20))!
@@ -114,19 +87,19 @@ public extension EIP712Hashable {
11487
// MARK: - Default implementation
11588

11689
var typehash: Data {
117-
keccak256(encodeType())
90+
Data(encodeType().bytes).sha3(.keccak256)
11891
}
11992

12093
func hash() throws -> Data {
12194
typealias SolidityValue = (value: Any, type: ABI.Element.ParameterType)
122-
var parametrs: [Data] = [self.typehash]
95+
var parameters: [Data] = [typehash]
12396
for case let (_, field) in Mirror(reflecting: self).children {
12497
let result: Data
12598
switch field {
12699
case let string as String:
127-
result = keccak256(string)
100+
result = Data(string.bytes).sha3(.keccak256)
128101
case let data as EIP712.Bytes:
129-
result = keccak256(data)
102+
result = data.sha3(.keccak256)
130103
case is EIP712.UInt8:
131104
result = ABIEncoder.encodeSingleType(type: .uint(bits: 8), value: field as AnyObject)!
132105
case is EIP712.UInt256:
@@ -143,28 +116,54 @@ public extension EIP712Hashable {
143116
}
144117
}
145118
guard result.count == 32 else { preconditionFailure("ABI encode error") }
146-
parametrs.append(result)
119+
parameters.append(result)
147120
}
148-
let encoded = parametrs.flatMap { $0.bytes }
149-
return keccak256(encoded)
121+
return Data(parameters.flatMap { $0.bytes }).sha3(.keccak256)
150122
}
151123
}
152124

153-
// Encode functions
154-
func eip712encode(domainSeparator: EIP712Hashable, message: EIP712Hashable) throws -> Data {
125+
public func eip712encode(domainSeparator: EIP712Hashable, message: EIP712Hashable) throws -> Data {
155126
let data = try Data([UInt8(0x19), UInt8(0x01)]) + domainSeparator.hash() + message.hash()
156-
return keccak256(data)
127+
return data.sha3(.keccak256)
157128
}
158129

159-
// MARK: - keccak256
160-
private func keccak256(_ data: [UInt8]) -> Data {
161-
Data(SHA3(variant: .keccak256).calculate(for: data))
162-
}
130+
// MARK: - Gnosis Safe Transaction model
163131

164-
private func keccak256(_ string: String) -> Data {
165-
keccak256(Array(string.utf8))
166-
}
132+
/// Gnosis Safe Transaction.
133+
/// https://docs.gnosis-safe.io/tutorials/tutorial_tx_service_initiate_sign
134+
public struct SafeTx: EIP712Hashable {
135+
/// Checksummed address
136+
let to: EIP712.Address
137+
/// Value in wei
138+
let value: EIP712.UInt256
139+
/// 0x prefixed hex string
140+
let data: EIP712.Bytes
141+
/// `0` CALL, `1` DELEGATE_CALL
142+
let operation: EIP712.UInt8
143+
/// Token address, **must be checksummed**, (held by the Safe) to be used as a refund to the sender, if `null` is Ether
144+
let gasToken: EIP712.Address
145+
/// Max gas to use in the transaction
146+
let safeTxGas: EIP712.UInt256
147+
/// Gast costs not related to the transaction execution (signature check, refund payment...)
148+
let baseGas: EIP712.UInt256
149+
/// Gas price used for the refund calculation
150+
let gasPrice: EIP712.UInt256
151+
/// Checksummed address of receiver of gas payment (or `null` if tx.origin)
152+
let refundReceiver: EIP712.Address
153+
/// Nonce of the Safe, transaction cannot be executed until Safe's nonce is not equal to this nonce
154+
let nonce: EIP712.UInt256
155+
156+
public init(to: EIP712.Address, value: EIP712.UInt256, data: EIP712.Bytes, operation: EIP712.UInt8, safeTxGas: EIP712.UInt256, baseGas: EIP712.UInt256, gasPrice: EIP712.UInt256, gasToken: EIP712.Address, refundReceiver: EIP712.Address, nonce: EIP712.UInt256) {
157+
self.to = to
158+
self.value = value
159+
self.data = data
160+
self.operation = operation
161+
self.safeTxGas = safeTxGas
162+
self.baseGas = baseGas
163+
self.gasPrice = gasPrice
164+
self.gasToken = gasToken
165+
self.refundReceiver = refundReceiver
166+
self.nonce = nonce
167+
}
167168

168-
private func keccak256(_ data: Data) -> Data {
169-
keccak256(data.bytes)
170169
}

0 commit comments

Comments
 (0)