@@ -16,9 +16,18 @@ import "./external/GnosisSafeMath.sol";
1616/// @title Gnosis Safe - A multisignature wallet with support for confirmations using signed messages based on ERC191.
1717/// @author Stefan George - <stefan@gnosis.io>
1818/// @author Richard Meissner - <richard@gnosis.io>
19- contract GnosisSafe
20- is EtherPaymentFallback , Singleton , ModuleManager , OwnerManager , SignatureDecoder , SecuredTokenTransfer , ISignatureValidatorConstants , FallbackManager , StorageAccessible , GuardManager {
21-
19+ contract GnosisSafe is
20+ EtherPaymentFallback ,
21+ Singleton ,
22+ ModuleManager ,
23+ OwnerManager ,
24+ SignatureDecoder ,
25+ SecuredTokenTransfer ,
26+ ISignatureValidatorConstants ,
27+ FallbackManager ,
28+ StorageAccessible ,
29+ GuardManager
30+ {
2231 using GnosisSafeMath for uint256 ;
2332
2433 string public constant VERSION = "1.3.0 " ;
@@ -38,26 +47,11 @@ contract GnosisSafe
3847 //);
3948 bytes32 private constant SAFE_MSG_TYPEHASH = 0x60b3cbf8b4a223d68d641b3b6ddf9a298e7f33710cf3d3a9d1146b5a6150fbca ;
4049
41- event SafeSetup (
42- address indexed initiator ,
43- address [] owners ,
44- uint256 threshold ,
45- address initializer ,
46- address fallbackHandler
47- );
48- event ApproveHash (
49- bytes32 indexed approvedHash ,
50- address indexed owner
51- );
52- event SignMsg (
53- bytes32 indexed msgHash
54- );
55- event ExecutionFailure (
56- bytes32 txHash , uint256 payment
57- );
58- event ExecutionSuccess (
59- bytes32 txHash , uint256 payment
60- );
50+ event SafeSetup (address indexed initiator , address [] owners , uint256 threshold , address initializer , address fallbackHandler );
51+ event ApproveHash (bytes32 indexed approvedHash , address indexed owner );
52+ event SignMsg (bytes32 indexed msgHash );
53+ event ExecutionFailure (bytes32 txHash , uint256 payment );
54+ event ExecutionSuccess (bytes32 txHash , uint256 payment );
6155
6256 uint256 public nonce;
6357 bytes32 private _deprecatedDomainSeparator;
@@ -92,9 +86,7 @@ contract GnosisSafe
9286 address paymentToken ,
9387 uint256 payment ,
9488 address payable paymentReceiver
95- )
96- external
97- {
89+ ) external {
9890 // setupOwners checks if the Threshold is already set, therefore preventing that this method is called twice
9991 setupOwners (_owners, _threshold);
10092 if (fallbackHandler != address (0 )) internalSetFallbackHandler (fallbackHandler);
@@ -132,20 +124,26 @@ contract GnosisSafe
132124 address gasToken ,
133125 address payable refundReceiver ,
134126 bytes memory signatures
135- )
136- public
137- virtual
138- payable
139- returns (bool success )
140- {
127+ ) public payable virtual returns (bool success ) {
141128 bytes32 txHash;
142129 // Use scope here to limit variable lifetime and prevent `stack too deep` errors
143130 {
144- bytes memory txHashData = encodeTransactionData (
145- to, value, data, operation, // Transaction info
146- safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, // Payment info
147- nonce
148- );
131+ bytes memory txHashData =
132+ encodeTransactionData (
133+ // Transaction info
134+ to,
135+ value,
136+ data,
137+ operation,
138+ safeTxGas,
139+ // Payment info
140+ baseGas,
141+ gasPrice,
142+ gasToken,
143+ refundReceiver,
144+ // Signature info
145+ nonce
146+ );
149147 // Increase nonce and execute transaction.
150148 nonce++ ;
151149 txHash = keccak256 (txHashData);
@@ -155,15 +153,26 @@ contract GnosisSafe
155153 address guard = getGuard ();
156154 if (guard != address (0 )) {
157155 Guard (guard).checkTransaction (
158- to, value, data, operation, // Transaction info
159- safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, // Payment info
160- signatures, msg .sender
156+ // Transaction info
157+ to,
158+ value,
159+ data,
160+ operation,
161+ safeTxGas,
162+ // Payment info
163+ baseGas,
164+ gasPrice,
165+ gasToken,
166+ refundReceiver,
167+ // Signature info
168+ signatures,
169+ msg .sender
161170 );
162171 }
163172 }
164173 // We require some gas to emit the events (at least 2500) after the execution and some to perform code until the execution (500)
165174 // We also include the 1/64 in the check that is not send along with a call to counteract potential shortings because of EIP-150
166- require (gasleft () >= (safeTxGas * 64 / 63 ).max (safeTxGas + 2500 ) + 500 , "GS010 " );
175+ require (gasleft () >= (( safeTxGas * 64 ) / 63 ).max (safeTxGas + 2500 ) + 500 , "GS010 " );
167176 // Use scope here to limit variable lifetime and prevent `stack too deep` errors
168177 {
169178 uint256 gasUsed = gasleft ();
@@ -190,10 +199,7 @@ contract GnosisSafe
190199 uint256 gasPrice ,
191200 address gasToken ,
192201 address payable refundReceiver
193- )
194- private
195- returns (uint256 payment )
196- {
202+ ) private returns (uint256 payment ) {
197203 // solhint-disable-next-line avoid-tx-origin
198204 address payable receiver = refundReceiver == address (0 ) ? payable (tx .origin ) : refundReceiver;
199205 if (gasToken == address (0 )) {
@@ -207,15 +213,16 @@ contract GnosisSafe
207213 }
208214
209215 /**
210- * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise.
211- * @param dataHash Hash of the data (could be either a message hash or transaction hash)
212- * @param data That should be signed (this is passed to an external validator contract)
213- * @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash.
214- */
215- function checkSignatures (bytes32 dataHash , bytes memory data , bytes memory signatures )
216- public
217- view
218- {
216+ * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise.
217+ * @param dataHash Hash of the data (could be either a message hash or transaction hash)
218+ * @param data That should be signed (this is passed to an external validator contract)
219+ * @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash.
220+ */
221+ function checkSignatures (
222+ bytes32 dataHash ,
223+ bytes memory data ,
224+ bytes memory signatures
225+ ) public view {
219226 // Load threshold to avoid multiple storage loads
220227 uint256 _threshold = threshold;
221228 // Check that a threshold is set
@@ -231,8 +238,8 @@ contract GnosisSafe
231238 uint256 i;
232239 for (i = 0 ; i < _threshold; i++ ) {
233240 (v, r, s) = signatureSplit (signatures, i);
234- // If v is 0 then it is a contract signature
235241 if (v == 0 ) {
242+ // If v is 0 then it is a contract signature
236243 // When handling contract signatures the address of the contract is encoded into r
237244 currentOwner = address (uint160 (uint256 (r)));
238245
@@ -260,23 +267,22 @@ contract GnosisSafe
260267 contractSignature := add (add (signatures, s), 0x20 )
261268 }
262269 require (ISignatureValidator (currentOwner).isValidSignature (data, contractSignature) == EIP1271_MAGIC_VALUE, "GS024 " );
263- // If v is 1 then it is an approved hash
264270 } else if (v == 1 ) {
271+ // If v is 1 then it is an approved hash
265272 // When handling approved hashes the address of the approver is encoded into r
266273 currentOwner = address (uint160 (uint256 (r)));
267274 // Hashes are automatically approved by the sender of the message or when they have been pre-approved via a separate transaction
268275 require (msg .sender == currentOwner || approvedHashes[currentOwner][dataHash] != 0 , "GS025 " );
269276 } else if (v > 30 ) {
277+ // If v > 30 then default va (27,28) has been adjusted for eth_sign flow
270278 // To support eth_sign and similar we adjust v and hash the messageHash with the Ethereum message prefix before applying ecrecover
271279 currentOwner = ecrecover (keccak256 (abi.encodePacked ("\x19Ethereum Signed Message:\n32 " , dataHash)), v - 4 , r, s);
272280 } else {
281+ // Default is the ecrecover flow with the provided data hash
273282 // Use ecrecover with the messageHash for EOA signatures
274283 currentOwner = ecrecover (dataHash, v, r, s);
275284 }
276- require (
277- currentOwner > lastOwner && owners[currentOwner] != address (0 ) && currentOwner != SENTINEL_OWNERS,
278- "GS026 "
279- );
285+ require (currentOwner > lastOwner && owners[currentOwner] != address (0 ) && currentOwner != SENTINEL_OWNERS, "GS026 " );
280286 lastOwner = currentOwner;
281287 }
282288 }
@@ -290,10 +296,12 @@ contract GnosisSafe
290296 /// @param operation Operation type of Safe transaction.
291297 /// @return Estimate without refunds and overhead fees (base transaction and payload data gas costs).
292298 /// @notice Deprecated in favor of common/StorageAccessible.sol and will be removed in next version.
293- function requiredTxGas (address to , uint256 value , bytes calldata data , Enum.Operation operation )
294- external
295- returns (uint256 )
296- {
299+ function requiredTxGas (
300+ address to ,
301+ uint256 value ,
302+ bytes calldata data ,
303+ Enum.Operation operation
304+ ) external returns (uint256 ) {
297305 uint256 startGas = gasleft ();
298306 // We don't provide an error message here, as we use it to return the estimate
299307 require (execute (to, value, data, operation, gasleft ()));
@@ -303,31 +311,26 @@ contract GnosisSafe
303311 }
304312
305313 /**
306- * @dev Marks a hash as approved. This can be used to validate a hash that is used by a signature.
307- * @param hashToApprove The hash that should be marked as approved for signatures that are verified by this contract.
308- */
309- function approveHash (bytes32 hashToApprove )
310- external
311- {
314+ * @dev Marks a hash as approved. This can be used to validate a hash that is used by a signature.
315+ * @param hashToApprove The hash that should be marked as approved for signatures that are verified by this contract.
316+ */
317+ function approveHash (bytes32 hashToApprove ) external {
312318 require (owners[msg .sender ] != address (0 ), "GS030 " );
313319 approvedHashes[msg .sender ][hashToApprove] = 1 ;
314320 emit ApproveHash (hashToApprove, msg .sender );
315321 }
316322
317323 /**
318- * @dev Marks a message as signed, so that it can be used with EIP-1271
319- * @notice Marks a message (`_data`) as signed.
320- * @param _data Arbitrary length data that should be marked as signed on the behalf of address(this)
321- */
322- function signMessage (bytes calldata _data )
323- external
324- authorized
325- {
324+ * @dev Marks a message as signed, so that it can be used with EIP-1271
325+ * @notice Marks a message (`_data`) as signed.
326+ * @param _data Arbitrary length data that should be marked as signed on the behalf of address(this)
327+ */
328+ function signMessage (bytes calldata _data ) external authorized {
326329 bytes32 msgHash = getMessageHash (_data);
327330 signedMessages[msgHash] = 1 ;
328331 emit SignMsg (msgHash);
329332 }
330-
333+
331334 /// @dev Returns the chain id used by this contract.
332335 function getChainId () public view returns (uint256 ) {
333336 uint256 id;
@@ -345,19 +348,9 @@ contract GnosisSafe
345348 /// @dev Returns hash of a message that can be signed by owners.
346349 /// @param message Message that should be hashed
347350 /// @return Message hash.
348- function getMessageHash (
349- bytes memory message
350- )
351- public
352- view
353- returns (bytes32 )
354- {
355- bytes32 safeMessageHash = keccak256 (
356- abi.encode (SAFE_MSG_TYPEHASH, keccak256 (message))
357- );
358- return keccak256 (
359- abi.encodePacked (bytes1 (0x19 ), bytes1 (0x01 ), domainSeparator (), safeMessageHash)
360- );
351+ function getMessageHash (bytes memory message ) public view returns (bytes32 ) {
352+ bytes32 safeMessageHash = keccak256 (abi.encode (SAFE_MSG_TYPEHASH, keccak256 (message)));
353+ return keccak256 (abi.encodePacked (bytes1 (0x19 ), bytes1 (0x01 ), domainSeparator (), safeMessageHash));
361354 }
362355
363356 /// @dev Returns the bytes that are hashed to be signed by owners.
@@ -383,14 +376,23 @@ contract GnosisSafe
383376 address gasToken ,
384377 address refundReceiver ,
385378 uint256 _nonce
386- )
387- public
388- view
389- returns (bytes memory )
390- {
391- bytes32 safeTxHash = keccak256 (
392- abi.encode (SAFE_TX_TYPEHASH, to, value, keccak256 (data), operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, _nonce)
393- );
379+ ) public view returns (bytes memory ) {
380+ bytes32 safeTxHash =
381+ keccak256 (
382+ abi.encode (
383+ SAFE_TX_TYPEHASH,
384+ to,
385+ value,
386+ keccak256 (data),
387+ operation,
388+ safeTxGas,
389+ baseGas,
390+ gasPrice,
391+ gasToken,
392+ refundReceiver,
393+ _nonce
394+ )
395+ );
394396 return abi.encodePacked (bytes1 (0x19 ), bytes1 (0x01 ), domainSeparator (), safeTxHash);
395397 }
396398
@@ -417,11 +419,7 @@ contract GnosisSafe
417419 address gasToken ,
418420 address refundReceiver ,
419421 uint256 _nonce
420- )
421- public
422- view
423- returns (bytes32 )
424- {
422+ ) public view returns (bytes32 ) {
425423 return keccak256 (encodeTransactionData (to, value, data, operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, _nonce));
426424 }
427425}
0 commit comments