@@ -6,6 +6,7 @@ import {console} from "forge-std/console.sol";
6
6
import {Script} from "forge-std/Script.sol " ;
7
7
import {IMulticall3} from "forge-std/interfaces/IMulticall3.sol " ;
8
8
import {Vm} from "forge-std/Vm.sol " ;
9
+ import {stdJson} from "forge-std/StdJson.sol " ;
9
10
10
11
import {IGnosisSafe, Enum} from "./IGnosisSafe.sol " ;
11
12
import {Signatures} from "./Signatures.sol " ;
@@ -332,7 +333,7 @@ abstract contract MultisigScript is Script {
332
333
return safes;
333
334
}
334
335
335
- function _transactionDatas (address [] memory _safes ) private view returns (bytes [] memory datas , uint256 value ) {
336
+ function _transactionDatas (address [] memory _safes ) internal view returns (bytes [] memory datas , uint256 value ) {
336
337
// Build the calls and sum the values
337
338
IMulticall3.Call3Value[] memory calls = _buildCalls ();
338
339
for (uint256 i = 0 ; i < calls.length ; i++ ) {
@@ -375,7 +376,8 @@ abstract contract MultisigScript is Script {
375
376
}
376
377
377
378
function _printDataToSign (address _safe , bytes memory _data , uint256 _value ) internal {
378
- bytes memory txData = _encodeTransactionData (_safe, _data, _value);
379
+ bytes memory txData =
380
+ _printDataHashes () ? _encodeTransactionData (_safe, _data, _value) : _encodeEIP712Json (_safe, _data, _value);
379
381
bytes32 hash = _getTransactionHash (_safe, _data, _value);
380
382
381
383
emit DataToSign (txData);
@@ -397,6 +399,14 @@ abstract contract MultisigScript is Script {
397
399
console.log ("############################### " );
398
400
}
399
401
402
+ // Controls whether the safe tx is printed as structured EIP-712 data, or just hashes.
403
+ //
404
+ // If you want to print and sign hashed EIP-712 data (domain + message hash) rather than the
405
+ // typed EIP-712 data struct, override this function and return `true`.
406
+ function _printDataHashes () internal view virtual returns (bool ) {
407
+ return false ;
408
+ }
409
+
400
410
function _executeTransaction (
401
411
address _safe ,
402
412
bytes memory _data ,
@@ -566,6 +576,39 @@ abstract contract MultisigScript is Script {
566
576
});
567
577
}
568
578
579
+ function _encodeEIP712Json (address _safe , bytes memory _data , uint256 _value ) internal returns (bytes memory ) {
580
+ string memory types = '{"EIP712Domain":[ ' '{"name":"chainId","type":"uint256"}, '
581
+ '{"name":"verifyingContract","type":"address"}], ' '"SafeTx":[ ' '{"name":"to","type":"address"}, '
582
+ '{"name":"value","type":"uint256"}, ' '{"name":"data","type":"bytes"}, '
583
+ '{"name":"operation","type":"uint8"}, ' '{"name":"safeTxGas","type":"uint256"}, '
584
+ '{"name":"baseGas","type":"uint256"}, ' '{"name":"gasPrice","type":"uint256"}, '
585
+ '{"name":"gasToken","type":"address"}, ' '{"name":"refundReceiver","type":"address"}, '
586
+ '{"name":"nonce","type":"uint256"}]} ' ;
587
+
588
+ string memory domain = stdJson.serialize ("domain " , "chainId " , uint256 (block .chainid ));
589
+ domain = stdJson.serialize ("domain " , "verifyingContract " , address (_safe));
590
+
591
+ string memory message = stdJson.serialize ("message " , "to " , MULTICALL3_ADDRESS);
592
+ message = stdJson.serialize ("message " , "value " , _value);
593
+ message = stdJson.serialize ("message " , "data " , _data);
594
+ message = stdJson.serialize (
595
+ "message " , "operation " , uint256 (_value == 0 ? Enum.Operation.DelegateCall : Enum.Operation.Call)
596
+ );
597
+ message = stdJson.serialize ("message " , "safeTxGas " , uint256 (0 ));
598
+ message = stdJson.serialize ("message " , "baseGas " , uint256 (0 ));
599
+ message = stdJson.serialize ("message " , "gasPrice " , uint256 (0 ));
600
+ message = stdJson.serialize ("message " , "gasToken " , address (0 ));
601
+ message = stdJson.serialize ("message " , "refundReceiver " , address (0 ));
602
+ message = stdJson.serialize ("message " , "nonce " , _getNonce (_safe));
603
+
604
+ string memory json = stdJson.serialize ("" , "primaryType " , string ("SafeTx " ));
605
+ json = stdJson.serialize ("" , "types " , types);
606
+ json = stdJson.serialize ("" , "domain " , domain);
607
+ json = stdJson.serialize ("" , "message " , message);
608
+
609
+ return abi.encodePacked (json);
610
+ }
611
+
569
612
function _execTransactionCalldata (address _safe , bytes memory _data , uint256 _value , bytes memory _signatures )
570
613
internal
571
614
pure
0 commit comments