Skip to content

Commit efd2218

Browse files
authored
Patch extension/Multicall (#588)
* Patch: special handling for multicall via forwarder * Fix build errors * Use OpenZeppelin 4.9.3 in lib/Address.sol * Test for multicall use with and without forwarder * Break out test cases * add test case with TokenERC721 usage * use ERC2771 context _msgSender and _msgData implementation
1 parent 745afa8 commit efd2218

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+607
-142
lines changed

contracts/base/ERC20Base.sol

+5
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,9 @@ contract ERC20Base is ContractMetadata, Multicall, Ownable, ERC20Permit, IMintab
103103
function _canSetOwner() internal view virtual override returns (bool) {
104104
return msg.sender == owner();
105105
}
106+
107+
/// @notice Returns the sender in the given execution context.
108+
function _msgSender() internal view override(Multicall, Context) returns (address) {
109+
return msg.sender;
110+
}
106111
}

contracts/base/ERC20Drop.sol

+5
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,9 @@ contract ERC20Drop is ContractMetadata, Multicall, Ownable, ERC20Permit, Primary
149149
function _canSetPrimarySaleRecipient() internal view virtual override returns (bool) {
150150
return msg.sender == owner();
151151
}
152+
153+
/// @notice Returns the sender in the given execution context.
154+
function _msgSender() internal view override(Multicall, Context) returns (address) {
155+
return msg.sender;
156+
}
152157
}

contracts/base/ERC20DropVote.sol

+5
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,9 @@ contract ERC20DropVote is ContractMetadata, Multicall, Ownable, ERC20Votes, Prim
127127
function _canSetPrimarySaleRecipient() internal view virtual override returns (bool) {
128128
return msg.sender == owner();
129129
}
130+
131+
/// @notice Returns the sender in the given execution context.
132+
function _msgSender() internal view override(Multicall, Context) returns (address) {
133+
return msg.sender;
134+
}
130135
}

contracts/base/ERC20Vote.sol

+5
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,9 @@ contract ERC20Vote is ContractMetadata, Multicall, Ownable, ERC20Votes, IMintabl
103103
function _canSetOwner() internal view virtual override returns (bool) {
104104
return msg.sender == owner();
105105
}
106+
107+
/// @notice Returns the sender in the given execution context.
108+
function _msgSender() internal view override(Multicall, Context) returns (address) {
109+
return msg.sender;
110+
}
106111
}

contracts/base/ERC721Base.sol

+5
Original file line numberDiff line numberDiff line change
@@ -202,4 +202,9 @@ contract ERC721Base is ERC721AQueryable, ContractMetadata, Multicall, Ownable, R
202202
function _canSetRoyaltyInfo() internal view virtual override returns (bool) {
203203
return msg.sender == owner();
204204
}
205+
206+
/// @notice Returns the sender in the given execution context.
207+
function _msgSender() internal view override(Multicall, Context) returns (address) {
208+
return msg.sender;
209+
}
205210
}

contracts/base/ERC721Drop.sol

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ pragma solidity ^0.8.0;
33

44
/// @author thirdweb
55

6-
import { ERC721A } from "../eip/ERC721AVirtualApprove.sol";
6+
import { ERC721A, Context } from "../eip/ERC721AVirtualApprove.sol";
77

88
import "../extension/ContractMetadata.sol";
99
import "../extension/Multicall.sol";
@@ -304,4 +304,9 @@ contract ERC721Drop is
304304
function _dropMsgSender() internal view virtual override returns (address) {
305305
return msg.sender;
306306
}
307+
308+
/// @notice Returns the sender in the given execution context.
309+
function _msgSender() internal view override(Multicall, Context) returns (address) {
310+
return msg.sender;
311+
}
307312
}

contracts/base/ERC721LazyMint.sol

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ pragma solidity ^0.8.0;
33

44
/// @author thirdweb
55

6-
import { ERC721A } from "../eip/ERC721AVirtualApprove.sol";
6+
import { ERC721A, Context } from "../eip/ERC721AVirtualApprove.sol";
77

88
import "../extension/ContractMetadata.sol";
99
import "../extension/Multicall.sol";
@@ -211,4 +211,9 @@ contract ERC721LazyMint is
211211
function _canSetRoyaltyInfo() internal view virtual override returns (bool) {
212212
return msg.sender == owner();
213213
}
214+
215+
/// @notice Returns the sender in the given execution context.
216+
function _msgSender() internal view override(Multicall, Context) returns (address) {
217+
return msg.sender;
218+
}
214219
}

contracts/base/ERC721Multiwrap.sol

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ pragma solidity ^0.8.0;
33

44
/// @author thirdweb
55

6-
import { ERC721A } from "../eip/ERC721AVirtualApprove.sol";
6+
import { ERC721A, Context } from "../eip/ERC721AVirtualApprove.sol";
77

88
import "../extension/ContractMetadata.sol";
99
import "../extension/Ownable.sol";
@@ -244,4 +244,9 @@ contract ERC721Multiwrap is Multicall, TokenStore, SoulboundERC721A, ERC721A, Co
244244
function _canSetRoyaltyInfo() internal view virtual override returns (bool) {
245245
return msg.sender == owner();
246246
}
247+
248+
/// @notice Returns the sender in the given execution context.
249+
function _msgSender() internal view override(Multicall, Context) returns (address) {
250+
return msg.sender;
251+
}
247252
}

contracts/extension/Multicall.sol

+13-2
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,22 @@ contract Multicall is IMulticall {
1919
* @param data The bytes data that makes up the batch of function calls to execute.
2020
* @return results The bytes data that makes up the result of the batch of function calls executed.
2121
*/
22-
function multicall(bytes[] calldata data) external virtual override returns (bytes[] memory results) {
22+
function multicall(bytes[] calldata data) external returns (bytes[] memory results) {
2323
results = new bytes[](data.length);
24+
address sender = _msgSender();
25+
bool isForwarder = msg.sender != sender;
2426
for (uint256 i = 0; i < data.length; i++) {
25-
results[i] = Address.functionDelegateCall(address(this), data[i]);
27+
if (isForwarder) {
28+
results[i] = Address.functionDelegateCall(address(this), abi.encodePacked(data[i], sender));
29+
} else {
30+
results[i] = Address.functionDelegateCall(address(this), data[i]);
31+
}
2632
}
2733
return results;
2834
}
35+
36+
/// @notice Returns the sender in the given execution context.
37+
function _msgSender() internal view virtual returns (address) {
38+
return msg.sender;
39+
}
2940
}

contracts/infra/ContractPublisher.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ contract ContractPublisher is IContractPublisher, ERC2771Context, AccessControlE
231231
}
232232

233233
/// @dev ERC2771Context overrides
234-
function _msgSender() internal view virtual override(Context, ERC2771Context) returns (address sender) {
234+
function _msgSender() internal view virtual override(Context, ERC2771Context, Multicall) returns (address sender) {
235235
return ERC2771Context._msgSender();
236236
}
237237

contracts/infra/TWFactory.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ contract TWFactory is Multicall, ERC2771Context, AccessControlEnumerable, IContr
130130
return implementation[_type][currentVersion[_type]];
131131
}
132132

133-
function _msgSender() internal view virtual override(Context, ERC2771Context) returns (address sender) {
133+
function _msgSender() internal view virtual override(Context, ERC2771Context, Multicall) returns (address sender) {
134134
return ERC2771Context._msgSender();
135135
}
136136

contracts/infra/TWFee.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ contract TWFee is ITWFee, Multicall, ERC2771Context, AccessControlEnumerable, IF
152152

153153
// ===== Getters =====
154154

155-
function _msgSender() internal view virtual override(Context, ERC2771Context) returns (address sender) {
155+
function _msgSender() internal view virtual override(Context, ERC2771Context, Multicall) returns (address sender) {
156156
return ERC2771Context._msgSender();
157157
}
158158

contracts/infra/TWMultichainRegistry.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ contract TWMultichainRegistry is ITWMultichainRegistry, Multicall, ERC2771Contex
106106
metadataUri = addressToMetadataUri[_chainId][_deployment];
107107
}
108108

109-
function _msgSender() internal view virtual override(Context, ERC2771Context) returns (address sender) {
109+
function _msgSender() internal view virtual override(Context, ERC2771Context, Multicall) returns (address sender) {
110110
return ERC2771Context._msgSender();
111111
}
112112

contracts/infra/TWRegistry.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ contract TWRegistry is Multicall, ERC2771Context, AccessControlEnumerable {
6060
return deployments[_deployer].length();
6161
}
6262

63-
function _msgSender() internal view virtual override(Context, ERC2771Context) returns (address sender) {
63+
function _msgSender() internal view virtual override(Context, ERC2771Context, Multicall) returns (address sender) {
6464
return ERC2771Context._msgSender();
6565
}
6666

contracts/infra/TWStatelessFactory.sol

+1-5
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,7 @@ contract TWStatelessFactory is Multicall, ERC2771Context, IContractFactory {
4141
}
4242
}
4343

44-
function _msgSender() internal view virtual override returns (address sender) {
44+
function _msgSender() internal view virtual override(Multicall, ERC2771Context) returns (address sender) {
4545
return ERC2771Context._msgSender();
4646
}
47-
48-
function _msgData() internal view virtual override returns (bytes calldata) {
49-
return ERC2771Context._msgData();
50-
}
5147
}

contracts/infra/registry/entrypoint/TWMultichainRegistryRouter.sol

+3-14
Original file line numberDiff line numberDiff line change
@@ -51,22 +51,11 @@ contract TWMultichainRegistryRouter is PermissionsEnumerableLogic, ERC2771Contex
5151
return hasRole(DEFAULT_ADMIN_ROLE, _msgSender());
5252
}
5353

54-
function _msgSender() internal view override(ERC2771ContextLogic, PermissionsLogic) returns (address sender) {
55-
if (isTrustedForwarder(msg.sender)) {
56-
// The assembly code is more direct than the Solidity version using `abi.decode`.
57-
assembly {
58-
sender := shr(96, calldataload(sub(calldatasize(), 20)))
59-
}
60-
} else {
61-
return msg.sender;
62-
}
54+
function _msgSender() internal view override(ERC2771ContextLogic, PermissionsLogic, Multicall) returns (address) {
55+
return ERC2771ContextLogic._msgSender();
6356
}
6457

6558
function _msgData() internal view override(ERC2771ContextLogic, PermissionsLogic) returns (bytes calldata) {
66-
if (isTrustedForwarder(msg.sender)) {
67-
return msg.data[:msg.data.length - 20];
68-
} else {
69-
return msg.data;
70-
}
59+
return ERC2771ContextLogic._msgData();
7160
}
7261
}

contracts/legacy-contracts/pre-builts/DropERC1155_V2.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ contract DropERC1155_V2 is
713713
internal
714714
view
715715
virtual
716-
override(ContextUpgradeable, ERC2771ContextUpgradeable)
716+
override(ContextUpgradeable, ERC2771ContextUpgradeable, Multicall)
717717
returns (address sender)
718718
{
719719
return ERC2771ContextUpgradeable._msgSender();

contracts/legacy-contracts/pre-builts/DropERC20_V2.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ contract DropERC20_V2 is
503503
internal
504504
view
505505
virtual
506-
override(ContextUpgradeable, ERC2771ContextUpgradeable)
506+
override(ContextUpgradeable, ERC2771ContextUpgradeable, Multicall)
507507
returns (address sender)
508508
{
509509
return ERC2771ContextUpgradeable._msgSender();

contracts/legacy-contracts/pre-builts/DropERC721_V3.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ contract DropERC721_V3 is
727727
internal
728728
view
729729
virtual
730-
override(ContextUpgradeable, ERC2771ContextUpgradeable)
730+
override(ContextUpgradeable, ERC2771ContextUpgradeable, Multicall)
731731
returns (address sender)
732732
{
733733
return ERC2771ContextUpgradeable._msgSender();

contracts/legacy-contracts/pre-builts/SignatureDrop_V4.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ contract SignatureDrop_V4 is
342342
internal
343343
view
344344
virtual
345-
override(ContextUpgradeable, ERC2771ContextUpgradeable)
345+
override(ContextUpgradeable, ERC2771ContextUpgradeable, Multicall)
346346
returns (address sender)
347347
{
348348
return ERC2771ContextUpgradeable._msgSender();

0 commit comments

Comments
 (0)