@@ -31,60 +31,8 @@ public extension EIP712.Address {
3131 }
3232}
3333
34+ // MARK: - Default implementation for EIP712Hashable
3435public extension EIP712Hashable {
35- private var name : String {
36- let fullName = " \( Self . self) "
37- let name = fullName. components ( separatedBy: " . " ) . last ?? fullName
38- return name
39- }
40-
41- private func dependencies( ) -> [ EIP712Hashable ] {
42- Mirror ( reflecting: self ) . children
43- . compactMap { $0. value as? EIP712Hashable }
44- . flatMap { [ $0] + $0. dependencies ( ) }
45- }
46-
47- private func encodePrimaryType( ) -> String {
48- let parametrs : [ String ] = Mirror ( reflecting: self ) . children. compactMap { key, value in
49- guard let key = key else { return nil }
50-
51- func checkIfValueIsNil( value: Any ) -> Bool {
52- let mirror = Mirror ( reflecting: value)
53- if mirror. displayStyle == . optional {
54- if mirror. children. count == 0 {
55- return true
56- }
57- }
58-
59- return false
60- }
61-
62- guard !checkIfValueIsNil( value: value) else { return nil }
63-
64- let typeName : String
65- switch value {
66- case is EIP712 . UInt8 : typeName = " uint8 "
67- case is EIP712 . UInt256 : typeName = " uint256 "
68- case is EIP712 . Address : typeName = " address "
69- case is EIP712 . Bytes : typeName = " bytes "
70- case let hashable as EIP712Hashable : typeName = hashable. name
71- default : typeName = " \( type ( of: value) ) " . lowercased ( )
72- }
73- return typeName + " " + key
74- }
75- return self . name + " ( " + parametrs. joined ( separator: " , " ) + " ) "
76- }
77-
78- func encodeType( ) -> String {
79- let dependencies = self . dependencies ( ) . map { $0. encodePrimaryType ( ) }
80- let selfPrimaryType = self . encodePrimaryType ( )
81-
82- let result = Set ( dependencies) . filter { $0 != selfPrimaryType }
83- return selfPrimaryType + result. sorted ( ) . joined ( )
84- }
85-
86- // MARK: - Default implementation
87-
8836 var typehash : Data {
8937 Data ( encodeType ( ) . bytes) . sha3 ( . keccak256)
9038 }
@@ -126,11 +74,74 @@ public func eip712encode(domainSeparator: EIP712Hashable, message: EIP712Hashabl
12674 return data. sha3 ( . keccak256)
12775}
12876
77+ // MARK: - Additional private and public extensions with support members
78+
79+ public extension EIP712Hashable {
80+ func encodeType( ) -> String {
81+ let dependencies = dependencies ( ) . map { $0. encodePrimaryType ( ) }
82+ let selfPrimaryType = encodePrimaryType ( )
83+
84+ let result = Set ( dependencies) . filter { $0 != selfPrimaryType }
85+ return selfPrimaryType + result. sorted ( ) . joined ( )
86+ }
87+ }
88+
89+ fileprivate extension EIP712Hashable {
90+ var name : String {
91+ let fullName = " \( Self . self) "
92+ let name = fullName. components ( separatedBy: " . " ) . last ?? fullName
93+ return name
94+ }
95+
96+ func dependencies( ) -> [ EIP712Hashable ] {
97+ Mirror ( reflecting: self ) . children
98+ . compactMap { $0. value as? EIP712Hashable }
99+ . flatMap { [ $0] + $0. dependencies ( ) }
100+ }
101+
102+ func encodePrimaryType( ) -> String {
103+ let parametrs : [ String ] = Mirror ( reflecting: self ) . children. compactMap { key, value in
104+ guard let key = key else { return nil }
105+
106+ func checkIfValueIsNil( value: Any ) -> Bool {
107+ let mirror = Mirror ( reflecting: value)
108+ if mirror. displayStyle == . optional {
109+ if mirror. children. count == 0 {
110+ return true
111+ }
112+ }
113+
114+ return false
115+ }
116+
117+ guard !checkIfValueIsNil( value: value) else { return nil }
118+
119+ let typeName : String
120+ switch value {
121+ case is EIP712 . UInt8 : typeName = " uint8 "
122+ case is EIP712 . UInt256 : typeName = " uint256 "
123+ case is EIP712 . Address : typeName = " address "
124+ case is EIP712 . Bytes : typeName = " bytes "
125+ case let hashable as EIP712Hashable : typeName = hashable. name
126+ default : typeName = " \( type ( of: value) ) " . lowercased ( )
127+ }
128+ return typeName + " " + key
129+ }
130+ return self . name + " ( " + parametrs. joined ( separator: " , " ) + " ) "
131+ }
132+ }
133+
129134// MARK: - Gnosis Safe Transaction model
130135
131136/// Gnosis Safe Transaction.
132137/// https://docs.gnosis-safe.io/tutorials/tutorial_tx_service_initiate_sign
133- public struct SafeTx : EIP712Hashable {
138+ ///
139+ /// Note for web3swift developers: **DO NOT CHANGE THE ORDER OF VARIABLES**.
140+ ///
141+ /// Changing the order will result in a different hash.
142+ /// Order must match the implementation of hash calculation in
143+ /// [`GnosisSafe.sol`](https://github.com/safe-global/safe-contracts/blob/main/contracts/GnosisSafe.sol#L126).
144+ public struct GnosisSafeTx : EIP712Hashable {
134145 /// Checksummed address
135146 let to : EIP712 . Address
136147 /// Value in wei
@@ -139,20 +150,29 @@ public struct SafeTx: EIP712Hashable {
139150 let data : EIP712 . Bytes
140151 /// `0` CALL, `1` DELEGATE_CALL
141152 let operation : EIP712 . UInt8
142- /// Token address, **must be checksummed**, (held by the Safe) to be used as a refund to the sender, if `null` is Ether
143- let gasToken : EIP712 . Address
144153 /// Max gas to use in the transaction
145154 let safeTxGas : EIP712 . UInt256
146155 /// Gast costs not related to the transaction execution (signature check, refund payment...)
147156 let baseGas : EIP712 . UInt256
148157 /// Gas price used for the refund calculation
149158 let gasPrice : EIP712 . UInt256
159+ /// Token address, **must be checksummed**, (held by the Safe) to be used as a refund to the sender, if `null` is Ether
160+ let gasToken : EIP712 . Address
150161 /// Checksummed address of receiver of gas payment (or `null` if tx.origin)
151162 let refundReceiver : EIP712 . Address
152163 /// Nonce of the Safe, transaction cannot be executed until Safe's nonce is not equal to this nonce
153164 let nonce : EIP712 . UInt256
154165
155- 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 ) {
166+ public init ( to: EIP712 . Address ,
167+ value: EIP712 . UInt256 ,
168+ data: EIP712 . Bytes ,
169+ operation: EIP712 . UInt8 ,
170+ safeTxGas: EIP712 . UInt256 ,
171+ baseGas: EIP712 . UInt256 ,
172+ gasPrice: EIP712 . UInt256 ,
173+ gasToken: EIP712 . Address ,
174+ refundReceiver: EIP712 . Address ,
175+ nonce: EIP712 . UInt256 ) {
156176 self . to = to
157177 self . value = value
158178 self . data = data
0 commit comments