1- import BigInt
21import CryptoSwift
32import Foundation
3+ import BigInt
44import 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
437public 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+
5528public 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