@@ -3,15 +3,18 @@ pragma solidity ^0.8.13;
33
44import {Vm} from "forge-std/Vm.sol " ;
55import {HTTP} from "../lib/solidity-http/src/HTTP.sol " ;
6- import {Safe as SafeSmartAccount} from "../lib/safe-smart-account/contracts/Safe.sol " ;
76import {MultiSendCallOnly} from "../lib/safe-smart-account/contracts/libraries/MultiSendCallOnly.sol " ;
87import {Enum} from "../lib/safe-smart-account/contracts/common/Enum.sol " ;
8+ import {ISafeSmartAccount} from "./ISafeSmartAccount.sol " ;
99
1010library Safe {
1111 using HTTP for * ;
1212
1313 Vm constant vm = Vm (address (bytes20 (uint160 (uint256 (keccak256 ("hevm cheat code " ))))));
1414
15+ // https://github.com/safe-global/safe-smart-account/blob/release/v1.4.1/contracts/libraries/SafeStorage.sol
16+ bytes32 constant SAFE_THRESHOLD_STORAGE_SLOT = bytes32 (uint256 (4 ));
17+
1518 error ApiKitUrlNotFound (uint256 chainId );
1619 error MultiSendCallOnlyNotFound (uint256 chainId );
1720 error ArrayLengthsMismatch (uint256 a , uint256 b );
@@ -34,6 +37,16 @@ library Safe {
3437 Instance[] instances;
3538 }
3639
40+ struct ExecTransactionParams {
41+ address to;
42+ uint256 value;
43+ bytes data;
44+ Enum.Operation operation;
45+ address sender;
46+ bytes signature;
47+ uint256 nonce;
48+ }
49+
3750 function initialize (Client storage self , address safe ) internal returns (Client storage ) {
3851 self.instances.push ();
3952 Instance storage i = self.instances[self.instances.length - 1 ];
@@ -88,7 +101,7 @@ library Safe {
88101 }
89102
90103 function getNonce (Client storage self ) internal view returns (uint256 ) {
91- return SafeSmartAccount ( payable ( instance (self).safe) ).nonce ();
104+ return ISafeSmartAccount ( instance (self).safe).nonce ();
92105 }
93106
94107 function getSafeTxHash (
@@ -99,35 +112,28 @@ library Safe {
99112 Enum.Operation operation ,
100113 uint256 nonce
101114 ) internal view returns (bytes32 ) {
102- return SafeSmartAccount ( payable ( instance (self).safe) ).getTransactionHash (
115+ return ISafeSmartAccount ( instance (self).safe).getTransactionHash (
103116 to, value, data, operation, 0 , 0 , 0 , address (0 ), address (0 ), nonce
104117 );
105118 }
106119
107120 // https://github.com/safe-global/safe-core-sdk/blob/r60/packages/api-kit/src/SafeApiKit.ts#L574
108- function proposeTransaction (
109- Client storage self ,
110- address to ,
111- uint256 value ,
112- bytes memory data ,
113- Enum.Operation operation ,
114- address sender ,
115- bytes memory signature ,
116- uint256 nonce
117- ) internal {
118- instance (self).requestBody = vm.serializeAddress (".proposeTransaction " , "to " , to);
119- instance (self).requestBody = vm.serializeUint (".proposeTransaction " , "value " , value);
120- instance (self).requestBody = vm.serializeBytes (".proposeTransaction " , "data " , data);
121- instance (self).requestBody = vm.serializeUint (".proposeTransaction " , "operation " , uint8 (operation));
121+ function proposeTransaction (Client storage self , ExecTransactionParams memory params ) internal {
122+ instance (self).requestBody = vm.serializeAddress (".proposeTransaction " , "to " , params.to);
123+ instance (self).requestBody = vm.serializeUint (".proposeTransaction " , "value " , params.value);
124+ instance (self).requestBody = vm.serializeBytes (".proposeTransaction " , "data " , params.data);
125+ instance (self).requestBody = vm.serializeUint (".proposeTransaction " , "operation " , uint8 (params.operation));
122126 instance (self).requestBody = vm.serializeBytes32 (
123- ".proposeTransaction " , "contractTransactionHash " , getSafeTxHash (self, to, value, data, operation, nonce)
127+ ".proposeTransaction " ,
128+ "contractTransactionHash " ,
129+ getSafeTxHash (self, params.to, params.value, params.data, params.operation, params.nonce)
124130 );
125- instance (self).requestBody = vm.serializeAddress (".proposeTransaction " , "sender " , sender);
126- instance (self).requestBody = vm.serializeBytes (".proposeTransaction " , "signature " , signature);
131+ instance (self).requestBody = vm.serializeAddress (".proposeTransaction " , "sender " , params. sender);
132+ instance (self).requestBody = vm.serializeBytes (".proposeTransaction " , "signature " , params. signature);
127133 instance (self).requestBody = vm.serializeUint (".proposeTransaction " , "safeTxGas " , 0 );
128134 instance (self).requestBody = vm.serializeUint (".proposeTransaction " , "baseGas " , 0 );
129135 instance (self).requestBody = vm.serializeUint (".proposeTransaction " , "gasPrice " , 0 );
130- instance (self).requestBody = vm.serializeUint (".proposeTransaction " , "nonce " , nonce);
136+ instance (self).requestBody = vm.serializeUint (".proposeTransaction " , "nonce " , params. nonce);
131137
132138 instance (self).http.instance ().POST (
133139 string .concat (
@@ -139,41 +145,36 @@ library Safe {
139145 ).withBody (instance (self).requestBody).request ();
140146 }
141147
142- function proposeTransaction (
143- Client storage self ,
144- address to ,
145- bytes memory data ,
146- Enum.Operation operation ,
147- address sender ,
148- bytes memory signature
149- ) internal {
150- return proposeTransaction (self, to, 0 , data, operation, sender, signature, getNonce (self));
151- }
152-
153148 function proposeTransaction (Client storage self , address to , bytes memory data , address sender ) internal {
154- return proposeTransaction (self, to, data, sender, string ("" ));
149+ ExecTransactionParams memory params = ExecTransactionParams ({
150+ to: to,
151+ value: 0 ,
152+ data: data,
153+ operation: Enum.Operation.Call,
154+ sender: sender,
155+ signature: sign (self, to, data, Enum.Operation.Call, sender, string ("" )),
156+ nonce: getNonce (self)
157+ });
158+ return proposeTransaction (self, params);
155159 }
156160
157161 function proposeTransaction (
158162 Client storage self ,
159163 address to ,
160164 bytes memory data ,
161- Enum.Operation operation ,
162165 address sender ,
163166 string memory derivationPath
164167 ) internal {
165- bytes memory signature = sign (self, to, data, operation, sender, derivationPath);
166- return proposeTransaction (self, to, 0 , data, operation, sender, signature, getNonce (self));
167- }
168-
169- function proposeTransaction (
170- Client storage self ,
171- address to ,
172- bytes memory data ,
173- address sender ,
174- string memory derivationPath
175- ) internal {
176- return proposeTransaction (self, to, data, Enum.Operation.Call, sender, derivationPath);
168+ ExecTransactionParams memory params = ExecTransactionParams ({
169+ to: to,
170+ value: 0 ,
171+ data: data,
172+ operation: Enum.Operation.Call,
173+ sender: sender,
174+ signature: sign (self, to, data, Enum.Operation.Call, sender, derivationPath),
175+ nonce: getNonce (self)
176+ });
177+ return proposeTransaction (self, params);
177178 }
178179
179180 function getProposeTransactionsTargetAndData (Client storage self , address [] memory targets , bytes [] memory datas )
@@ -206,14 +207,32 @@ library Safe {
206207 ) internal {
207208 (address to , bytes memory data ) = getProposeTransactionsTargetAndData (self, targets, datas);
208209 // using DelegateCall to preserve msg.sender across sub-calls
209- return proposeTransaction (self, to, data, Enum.Operation.DelegateCall, sender, derivationPath);
210+ ExecTransactionParams memory params = ExecTransactionParams ({
211+ to: to,
212+ value: 0 ,
213+ data: data,
214+ operation: Enum.Operation.DelegateCall,
215+ sender: sender,
216+ signature: sign (self, to, data, Enum.Operation.DelegateCall, sender, derivationPath),
217+ nonce: getNonce (self)
218+ });
219+ return proposeTransaction (self, params);
210220 }
211221
212222 function getExecTransactionData (Client storage self , address to , bytes memory data , address sender )
213223 internal
214224 returns (bytes memory )
215225 {
216- return getExecTransactionData (self, to, data, sender, string ("" ));
226+ ExecTransactionParams memory params = ExecTransactionParams ({
227+ to: to,
228+ value: 0 ,
229+ data: data,
230+ operation: Enum.Operation.Call,
231+ sender: sender,
232+ signature: sign (self, to, data, Enum.Operation.Call, sender, string ("" )),
233+ nonce: getNonce (self)
234+ });
235+ return getExecTransactionData (self, params);
217236 }
218237
219238 function getExecTransactionData (
@@ -223,7 +242,16 @@ library Safe {
223242 address sender ,
224243 string memory derivationPath
225244 ) internal returns (bytes memory ) {
226- return getExecTransactionData (self, to, data, Enum.Operation.Call, sender, derivationPath);
245+ ExecTransactionParams memory params = ExecTransactionParams ({
246+ to: to,
247+ value: 0 ,
248+ data: data,
249+ operation: Enum.Operation.Call,
250+ sender: sender,
251+ signature: sign (self, to, data, Enum.Operation.Call, sender, derivationPath),
252+ nonce: getNonce (self)
253+ });
254+ return getExecTransactionData (self, params);
227255 }
228256
229257 function getExecTransactionsData (
@@ -244,20 +272,26 @@ library Safe {
244272 ) internal returns (bytes memory ) {
245273 (address to , bytes memory data ) = getProposeTransactionsTargetAndData (self, targets, datas);
246274 // using DelegateCall to preserve msg.sender across sub-calls
247- return getExecTransactionData (self, to, data, Enum.Operation.DelegateCall, sender, derivationPath);
275+ ExecTransactionParams memory params = ExecTransactionParams ({
276+ to: to,
277+ value: 0 ,
278+ data: data,
279+ operation: Enum.Operation.DelegateCall,
280+ sender: sender,
281+ signature: sign (self, to, data, Enum.Operation.DelegateCall, sender, derivationPath),
282+ nonce: getNonce (self)
283+ });
284+ return getExecTransactionData (self, params);
248285 }
249286
250- function getExecTransactionData (
251- Client storage self ,
252- address to ,
253- bytes memory data ,
254- Enum.Operation operation ,
255- address sender ,
256- string memory derivationPath
257- ) internal returns (bytes memory ) {
258- bytes memory signature = sign (self, to, data, operation, sender, derivationPath);
287+ function getExecTransactionData (Client storage , ExecTransactionParams memory params )
288+ internal
289+ pure
290+ returns (bytes memory )
291+ {
259292 return abi.encodeCall (
260- SafeSmartAccount.execTransaction, (to, 0 , data, operation, 0 , 0 , 0 , address (0 ), payable (0 ), signature)
293+ ISafeSmartAccount.execTransaction,
294+ (params.to, 0 , params.data, params.operation, 0 , 0 , 0 , address (0 ), payable (0 ), params.signature)
261295 );
262296 }
263297
0 commit comments