@@ -27,15 +27,16 @@ interface IMultiCall {
27
27
// you need to know is the interface above.
28
28
29
29
library SafeCall {
30
- function safeCall (address target , bytes calldata data , uint256 contextdepth )
30
+ function safeCall (address target , bytes calldata data , address sender , uint256 contextdepth )
31
31
internal
32
32
returns (bool success , bytes memory returndata )
33
33
{
34
34
assembly ("memory-safe" ) {
35
35
returndata := mload (0x40 )
36
36
calldatacopy (returndata, data.offset, data.length )
37
+ mstore (add (returndata, data.length ), shl (0x60 , sender))
37
38
let beforeGas := gas ()
38
- success := call (gas (), target, 0x00 , returndata, data.length , 0x00 , 0x00 )
39
+ success := call (gas (), target, 0x00 , returndata, add ( 0x14 , data.length ) , 0x00 , 0x00 )
39
40
// `verbatim` can't work in inline assembly. Assignment of a value to a variable costs
40
41
// gas (although how much is unpredictable because it depends on the Yul/IR optimizer),
41
42
// as does the `GAS` opcode itself. Therefore, the `gas()` below returns less than the
@@ -76,11 +77,12 @@ library SafeCall {
76
77
77
78
/// This version of `safeCall` omits the OOG check because it bubbles the revert if the call
78
79
/// reverts. Therefore, `success` is always `true`.
79
- function safeCall (address target , bytes calldata data ) internal returns (bool success , bytes memory returndata ) {
80
+ function safeCall (address target , bytes calldata data , address sender ) internal returns (bool success , bytes memory returndata ) {
80
81
assembly ("memory-safe" ) {
81
82
returndata := mload (0x40 )
82
83
calldatacopy (returndata, data.offset, data.length )
83
- success := call (gas (), target, 0x00 , returndata, data.length , 0x00 , 0x00 )
84
+ mstore (add (returndata, data.length ), shl (0x60 , sender))
85
+ success := call (gas (), target, 0x00 , returndata, add (0x14 , data.length ), 0x00 , 0x00 )
84
86
let dst := add (0x20 , returndata)
85
87
returndatacopy (dst, 0x00 , returndatasize ())
86
88
if iszero (success) { revert (dst, returndatasize ()) }
@@ -149,7 +151,7 @@ library UnsafeArray {
149
151
function unsafeSet (Result[] memory a , uint256 i , bool success , bytes memory data ) internal pure {
150
152
assembly ("memory-safe" ) {
151
153
let dst := mload (add (add (0x20 , shl (0x05 , i)), a))
152
- mstore (dst, and ( 0x01 , success) )
154
+ mstore (dst, success)
153
155
mstore (add (0x20 , dst), data)
154
156
}
155
157
}
@@ -218,10 +220,19 @@ contract MultiCall {
218
220
using UnsafeReturn for Result[];
219
221
220
222
constructor () {
221
- assert (address (this ) == 0x000000000000175a8b9bC6d539B3708EEd92EA6c || block .chainid == 31337 );
223
+ assert (uint160 (address (this )) >> 112 == 0 || block .chainid == 31337 );
224
+ }
225
+
226
+ function _msgSender () private view returns (address sender ) {
227
+ if ((sender = msg .sender ) == address (this )) {
228
+ assembly ("memory-safe" ) {
229
+ sender := shr (0x60 , calldataload (sub (calldatasize (), 0x14 )))
230
+ }
231
+ }
222
232
}
223
233
224
234
function multicall (Call[] calldata calls , uint256 contextdepth ) internal returns (Result[] memory result ) {
235
+ address sender = _msgSender ();
225
236
result = new Result [](calls.length );
226
237
for (uint256 i; i < calls.length ; i = i.unsafeInc ()) {
227
238
(address target , bytes calldata data , RevertPolicy revertPolicy ) = calls.unsafeGet (i);
@@ -230,9 +241,9 @@ contract MultiCall {
230
241
if (revertPolicy == RevertPolicy.REVERT) {
231
242
// We don't need to use the OOG-protected `safeCall` here because an OOG will result
232
243
// in a bubbled revert anyways.
233
- (success, returndata) = target.safeCall (data);
244
+ (success, returndata) = target.safeCall (data, sender );
234
245
} else {
235
- (success, returndata) = target.safeCall (data, contextdepth);
246
+ (success, returndata) = target.safeCall (data, sender, contextdepth);
236
247
// This could be implemented in assembly as (equivalently) `(revertPolicy ==
237
248
// RevertPolicy.STOP) > success`, but that only optimizes the `success == false`
238
249
// condition and significantly compromises readability.
0 commit comments