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

Lines changed: 5 additions & 0 deletions
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

Lines changed: 5 additions & 0 deletions
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

Lines changed: 5 additions & 0 deletions
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

Lines changed: 5 additions & 0 deletions
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

Lines changed: 5 additions & 0 deletions
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

Lines changed: 6 additions & 1 deletion
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

Lines changed: 6 additions & 1 deletion
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

Lines changed: 6 additions & 1 deletion
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

Lines changed: 13 additions & 2 deletions
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

Lines changed: 1 addition & 1 deletion
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

0 commit comments

Comments
 (0)