Skip to content

Commit

Permalink
Patch extension/Multicall (#588)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
nkrishang authored Dec 18, 2023
1 parent 745afa8 commit efd2218
Show file tree
Hide file tree
Showing 51 changed files with 607 additions and 142 deletions.
5 changes: 5 additions & 0 deletions contracts/base/ERC20Base.sol
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,9 @@ contract ERC20Base is ContractMetadata, Multicall, Ownable, ERC20Permit, IMintab
function _canSetOwner() internal view virtual override returns (bool) {
return msg.sender == owner();
}

/// @notice Returns the sender in the given execution context.
function _msgSender() internal view override(Multicall, Context) returns (address) {
return msg.sender;
}
}
5 changes: 5 additions & 0 deletions contracts/base/ERC20Drop.sol
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,9 @@ contract ERC20Drop is ContractMetadata, Multicall, Ownable, ERC20Permit, Primary
function _canSetPrimarySaleRecipient() internal view virtual override returns (bool) {
return msg.sender == owner();
}

/// @notice Returns the sender in the given execution context.
function _msgSender() internal view override(Multicall, Context) returns (address) {
return msg.sender;
}
}
5 changes: 5 additions & 0 deletions contracts/base/ERC20DropVote.sol
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,9 @@ contract ERC20DropVote is ContractMetadata, Multicall, Ownable, ERC20Votes, Prim
function _canSetPrimarySaleRecipient() internal view virtual override returns (bool) {
return msg.sender == owner();
}

/// @notice Returns the sender in the given execution context.
function _msgSender() internal view override(Multicall, Context) returns (address) {
return msg.sender;
}
}
5 changes: 5 additions & 0 deletions contracts/base/ERC20Vote.sol
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,9 @@ contract ERC20Vote is ContractMetadata, Multicall, Ownable, ERC20Votes, IMintabl
function _canSetOwner() internal view virtual override returns (bool) {
return msg.sender == owner();
}

/// @notice Returns the sender in the given execution context.
function _msgSender() internal view override(Multicall, Context) returns (address) {
return msg.sender;
}
}
5 changes: 5 additions & 0 deletions contracts/base/ERC721Base.sol
Original file line number Diff line number Diff line change
Expand Up @@ -202,4 +202,9 @@ contract ERC721Base is ERC721AQueryable, ContractMetadata, Multicall, Ownable, R
function _canSetRoyaltyInfo() internal view virtual override returns (bool) {
return msg.sender == owner();
}

/// @notice Returns the sender in the given execution context.
function _msgSender() internal view override(Multicall, Context) returns (address) {
return msg.sender;
}
}
7 changes: 6 additions & 1 deletion contracts/base/ERC721Drop.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity ^0.8.0;

/// @author thirdweb

import { ERC721A } from "../eip/ERC721AVirtualApprove.sol";
import { ERC721A, Context } from "../eip/ERC721AVirtualApprove.sol";

import "../extension/ContractMetadata.sol";
import "../extension/Multicall.sol";
Expand Down Expand Up @@ -304,4 +304,9 @@ contract ERC721Drop is
function _dropMsgSender() internal view virtual override returns (address) {
return msg.sender;
}

/// @notice Returns the sender in the given execution context.
function _msgSender() internal view override(Multicall, Context) returns (address) {
return msg.sender;
}
}
7 changes: 6 additions & 1 deletion contracts/base/ERC721LazyMint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity ^0.8.0;

/// @author thirdweb

import { ERC721A } from "../eip/ERC721AVirtualApprove.sol";
import { ERC721A, Context } from "../eip/ERC721AVirtualApprove.sol";

import "../extension/ContractMetadata.sol";
import "../extension/Multicall.sol";
Expand Down Expand Up @@ -211,4 +211,9 @@ contract ERC721LazyMint is
function _canSetRoyaltyInfo() internal view virtual override returns (bool) {
return msg.sender == owner();
}

/// @notice Returns the sender in the given execution context.
function _msgSender() internal view override(Multicall, Context) returns (address) {
return msg.sender;
}
}
7 changes: 6 additions & 1 deletion contracts/base/ERC721Multiwrap.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity ^0.8.0;

/// @author thirdweb

import { ERC721A } from "../eip/ERC721AVirtualApprove.sol";
import { ERC721A, Context } from "../eip/ERC721AVirtualApprove.sol";

import "../extension/ContractMetadata.sol";
import "../extension/Ownable.sol";
Expand Down Expand Up @@ -244,4 +244,9 @@ contract ERC721Multiwrap is Multicall, TokenStore, SoulboundERC721A, ERC721A, Co
function _canSetRoyaltyInfo() internal view virtual override returns (bool) {
return msg.sender == owner();
}

/// @notice Returns the sender in the given execution context.
function _msgSender() internal view override(Multicall, Context) returns (address) {
return msg.sender;
}
}
15 changes: 13 additions & 2 deletions contracts/extension/Multicall.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,22 @@ contract Multicall is IMulticall {
* @param data The bytes data that makes up the batch of function calls to execute.
* @return results The bytes data that makes up the result of the batch of function calls executed.
*/
function multicall(bytes[] calldata data) external virtual override returns (bytes[] memory results) {
function multicall(bytes[] calldata data) external returns (bytes[] memory results) {
results = new bytes[](data.length);
address sender = _msgSender();
bool isForwarder = msg.sender != sender;
for (uint256 i = 0; i < data.length; i++) {
results[i] = Address.functionDelegateCall(address(this), data[i]);
if (isForwarder) {
results[i] = Address.functionDelegateCall(address(this), abi.encodePacked(data[i], sender));
} else {
results[i] = Address.functionDelegateCall(address(this), data[i]);
}
}
return results;
}

/// @notice Returns the sender in the given execution context.
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
}
2 changes: 1 addition & 1 deletion contracts/infra/ContractPublisher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ contract ContractPublisher is IContractPublisher, ERC2771Context, AccessControlE
}

/// @dev ERC2771Context overrides
function _msgSender() internal view virtual override(Context, ERC2771Context) returns (address sender) {
function _msgSender() internal view virtual override(Context, ERC2771Context, Multicall) returns (address sender) {
return ERC2771Context._msgSender();
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/infra/TWFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ contract TWFactory is Multicall, ERC2771Context, AccessControlEnumerable, IContr
return implementation[_type][currentVersion[_type]];
}

function _msgSender() internal view virtual override(Context, ERC2771Context) returns (address sender) {
function _msgSender() internal view virtual override(Context, ERC2771Context, Multicall) returns (address sender) {
return ERC2771Context._msgSender();
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/infra/TWFee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ contract TWFee is ITWFee, Multicall, ERC2771Context, AccessControlEnumerable, IF

// ===== Getters =====

function _msgSender() internal view virtual override(Context, ERC2771Context) returns (address sender) {
function _msgSender() internal view virtual override(Context, ERC2771Context, Multicall) returns (address sender) {
return ERC2771Context._msgSender();
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/infra/TWMultichainRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ contract TWMultichainRegistry is ITWMultichainRegistry, Multicall, ERC2771Contex
metadataUri = addressToMetadataUri[_chainId][_deployment];
}

function _msgSender() internal view virtual override(Context, ERC2771Context) returns (address sender) {
function _msgSender() internal view virtual override(Context, ERC2771Context, Multicall) returns (address sender) {
return ERC2771Context._msgSender();
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/infra/TWRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ contract TWRegistry is Multicall, ERC2771Context, AccessControlEnumerable {
return deployments[_deployer].length();
}

function _msgSender() internal view virtual override(Context, ERC2771Context) returns (address sender) {
function _msgSender() internal view virtual override(Context, ERC2771Context, Multicall) returns (address sender) {
return ERC2771Context._msgSender();
}

Expand Down
6 changes: 1 addition & 5 deletions contracts/infra/TWStatelessFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,7 @@ contract TWStatelessFactory is Multicall, ERC2771Context, IContractFactory {
}
}

function _msgSender() internal view virtual override returns (address sender) {
function _msgSender() internal view virtual override(Multicall, ERC2771Context) returns (address sender) {
return ERC2771Context._msgSender();
}

function _msgData() internal view virtual override returns (bytes calldata) {
return ERC2771Context._msgData();
}
}
17 changes: 3 additions & 14 deletions contracts/infra/registry/entrypoint/TWMultichainRegistryRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,11 @@ contract TWMultichainRegistryRouter is PermissionsEnumerableLogic, ERC2771Contex
return hasRole(DEFAULT_ADMIN_ROLE, _msgSender());
}

function _msgSender() internal view override(ERC2771ContextLogic, PermissionsLogic) returns (address sender) {
if (isTrustedForwarder(msg.sender)) {
// The assembly code is more direct than the Solidity version using `abi.decode`.
assembly {
sender := shr(96, calldataload(sub(calldatasize(), 20)))
}
} else {
return msg.sender;
}
function _msgSender() internal view override(ERC2771ContextLogic, PermissionsLogic, Multicall) returns (address) {
return ERC2771ContextLogic._msgSender();
}

function _msgData() internal view override(ERC2771ContextLogic, PermissionsLogic) returns (bytes calldata) {
if (isTrustedForwarder(msg.sender)) {
return msg.data[:msg.data.length - 20];
} else {
return msg.data;
}
return ERC2771ContextLogic._msgData();
}
}
2 changes: 1 addition & 1 deletion contracts/legacy-contracts/pre-builts/DropERC1155_V2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ contract DropERC1155_V2 is
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
override(ContextUpgradeable, ERC2771ContextUpgradeable, Multicall)
returns (address sender)
{
return ERC2771ContextUpgradeable._msgSender();
Expand Down
2 changes: 1 addition & 1 deletion contracts/legacy-contracts/pre-builts/DropERC20_V2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ contract DropERC20_V2 is
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
override(ContextUpgradeable, ERC2771ContextUpgradeable, Multicall)
returns (address sender)
{
return ERC2771ContextUpgradeable._msgSender();
Expand Down
2 changes: 1 addition & 1 deletion contracts/legacy-contracts/pre-builts/DropERC721_V3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ contract DropERC721_V3 is
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
override(ContextUpgradeable, ERC2771ContextUpgradeable, Multicall)
returns (address sender)
{
return ERC2771ContextUpgradeable._msgSender();
Expand Down
2 changes: 1 addition & 1 deletion contracts/legacy-contracts/pre-builts/SignatureDrop_V4.sol
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ contract SignatureDrop_V4 is
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
override(ContextUpgradeable, ERC2771ContextUpgradeable, Multicall)
returns (address sender)
{
return ERC2771ContextUpgradeable._msgSender();
Expand Down
Loading

0 comments on commit efd2218

Please sign in to comment.