Skip to content

Commit ccffe67

Browse files
committed
Add _msgSender() trick
Fixes solidstate-network#132 Enables MetaTransaction facets and [Delegatable](https://github.com/delegatable/delegatable-sol/blob/main/contracts/diamond/README.md).
1 parent 92cd5fd commit ccffe67

File tree

8 files changed

+140
-33
lines changed

8 files changed

+140
-33
lines changed

contracts/access/ownable/OwnableInternal.sol

+23-3
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ abstract contract OwnableInternal is IOwnableInternal {
1212
using OwnableStorage for OwnableStorage.Layout;
1313

1414
modifier onlyOwner() {
15-
require(msg.sender == _owner(), 'Ownable: sender must be owner');
15+
require(_msgSender() == _owner(), 'Ownable: sender must be owner');
1616
_;
1717
}
1818

1919
modifier onlyTransitiveOwner() {
2020
require(
21-
msg.sender == _transitiveOwner(),
21+
_msgSender() == _transitiveOwner(),
2222
'Ownable: sender must be transitive owner'
2323
);
2424
_;
@@ -44,6 +44,26 @@ abstract contract OwnableInternal is IOwnableInternal {
4444

4545
function _transferOwnership(address account) internal virtual {
4646
OwnableStorage.layout().setOwner(account);
47-
emit OwnershipTransferred(msg.sender, account);
47+
emit OwnershipTransferred(_msgSender(), account);
48+
}
49+
50+
/*
51+
* @notice Overrides the msgSender to enable delegation message signing.
52+
* @returns address - The account whose authority is being acted on.
53+
*/
54+
function _msgSender() internal view virtual returns (address sender) {
55+
if (msg.sender == address(this)) {
56+
bytes memory array = msg.data;
57+
uint256 index = msg.data.length;
58+
assembly {
59+
sender := and(
60+
mload(add(array, index)),
61+
0xffffffffffffffffffffffffffffffffffffffff
62+
)
63+
}
64+
} else {
65+
sender = msg.sender;
66+
}
67+
return sender;
4868
}
4969
}

contracts/security/PausableInternal.sol

+22-2
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,34 @@ abstract contract PausableInternal {
3737
*/
3838
function _pause() internal virtual whenNotPaused {
3939
PausableStorage.layout().paused = true;
40-
emit Paused(msg.sender);
40+
emit Paused(_msgSender());
4141
}
4242

4343
/**
4444
* @notice Triggers unpaused state, when contract is paused.
4545
*/
4646
function _unpause() internal virtual whenPaused {
4747
PausableStorage.layout().paused = false;
48-
emit Unpaused(msg.sender);
48+
emit Unpaused(_msgSender());
49+
}
50+
51+
/*
52+
* @notice Overrides the msgSender to enable delegation message signing.
53+
* @returns address - The account whose authority is being acted on.
54+
*/
55+
function _msgSender() internal view virtual returns (address sender) {
56+
if (msg.sender == address(this)) {
57+
bytes memory array = msg.data;
58+
uint256 index = msg.data.length;
59+
assembly {
60+
sender := and(
61+
mload(add(array, index)),
62+
0xffffffffffffffffffffffffffffffffffffffff
63+
)
64+
}
65+
} else {
66+
sender = msg.sender;
67+
}
68+
return sender;
4969
}
5070
}

contracts/token/ERC1155/base/ERC1155Base.sol

+7-7
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,13 @@ abstract contract ERC1155Base is IERC1155Base, ERC1155BaseInternal {
7373
*/
7474
function setApprovalForAll(address operator, bool status) public virtual {
7575
require(
76-
msg.sender != operator,
76+
_msgSender() != operator,
7777
'ERC1155: setting approval status for self'
7878
);
79-
ERC1155BaseStorage.layout().operatorApprovals[msg.sender][
79+
ERC1155BaseStorage.layout().operatorApprovals[_msgSender()][
8080
operator
8181
] = status;
82-
emit ApprovalForAll(msg.sender, operator, status);
82+
emit ApprovalForAll(_msgSender(), operator, status);
8383
}
8484

8585
/**
@@ -93,10 +93,10 @@ abstract contract ERC1155Base is IERC1155Base, ERC1155BaseInternal {
9393
bytes memory data
9494
) public virtual {
9595
require(
96-
from == msg.sender || isApprovedForAll(from, msg.sender),
96+
from == _msgSender() || isApprovedForAll(from, _msgSender()),
9797
'ERC1155: caller is not owner nor approved'
9898
);
99-
_safeTransfer(msg.sender, from, to, id, amount, data);
99+
_safeTransfer(_msgSender(), from, to, id, amount, data);
100100
}
101101

102102
/**
@@ -110,9 +110,9 @@ abstract contract ERC1155Base is IERC1155Base, ERC1155BaseInternal {
110110
bytes memory data
111111
) public virtual {
112112
require(
113-
from == msg.sender || isApprovedForAll(from, msg.sender),
113+
from == _msgSender() || isApprovedForAll(from, _msgSender()),
114114
'ERC1155: caller is not owner nor approved'
115115
);
116-
_safeTransferBatch(msg.sender, from, to, ids, amounts, data);
116+
_safeTransferBatch(_msgSender(), from, to, ids, amounts, data);
117117
}
118118
}

contracts/token/ERC1155/base/ERC1155BaseInternal.sol

+37-10
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ abstract contract ERC1155BaseInternal is IERC1155Internal {
5050
require(account != address(0), 'ERC1155: mint to the zero address');
5151

5252
_beforeTokenTransfer(
53-
msg.sender,
53+
_msgSender(),
5454
address(0),
5555
account,
5656
_asSingletonArray(id),
@@ -60,7 +60,7 @@ abstract contract ERC1155BaseInternal is IERC1155Internal {
6060

6161
ERC1155BaseStorage.layout().balances[id][account] += amount;
6262

63-
emit TransferSingle(msg.sender, address(0), account, id, amount);
63+
emit TransferSingle(_msgSender(), address(0), account, id, amount);
6464
}
6565

6666
/**
@@ -79,7 +79,7 @@ abstract contract ERC1155BaseInternal is IERC1155Internal {
7979
_mint(account, id, amount, data);
8080

8181
_doSafeTransferAcceptanceCheck(
82-
msg.sender,
82+
_msgSender(),
8383
address(0),
8484
account,
8585
id,
@@ -109,7 +109,7 @@ abstract contract ERC1155BaseInternal is IERC1155Internal {
109109
);
110110

111111
_beforeTokenTransfer(
112-
msg.sender,
112+
_msgSender(),
113113
address(0),
114114
account,
115115
ids,
@@ -127,7 +127,7 @@ abstract contract ERC1155BaseInternal is IERC1155Internal {
127127
}
128128
}
129129

130-
emit TransferBatch(msg.sender, address(0), account, ids, amounts);
130+
emit TransferBatch(_msgSender(), address(0), account, ids, amounts);
131131
}
132132

133133
/**
@@ -146,7 +146,7 @@ abstract contract ERC1155BaseInternal is IERC1155Internal {
146146
_mintBatch(account, ids, amounts, data);
147147

148148
_doSafeBatchTransferAcceptanceCheck(
149-
msg.sender,
149+
_msgSender(),
150150
address(0),
151151
account,
152152
ids,
@@ -169,7 +169,7 @@ abstract contract ERC1155BaseInternal is IERC1155Internal {
169169
require(account != address(0), 'ERC1155: burn from the zero address');
170170

171171
_beforeTokenTransfer(
172-
msg.sender,
172+
_msgSender(),
173173
account,
174174
address(0),
175175
_asSingletonArray(id),
@@ -189,7 +189,7 @@ abstract contract ERC1155BaseInternal is IERC1155Internal {
189189
balances[account] -= amount;
190190
}
191191

192-
emit TransferSingle(msg.sender, account, address(0), id, amount);
192+
emit TransferSingle(_msgSender(), account, address(0), id, amount);
193193
}
194194

195195
/**
@@ -209,7 +209,14 @@ abstract contract ERC1155BaseInternal is IERC1155Internal {
209209
'ERC1155: ids and amounts length mismatch'
210210
);
211211

212-
_beforeTokenTransfer(msg.sender, account, address(0), ids, amounts, '');
212+
_beforeTokenTransfer(
213+
_msgSender(),
214+
account,
215+
address(0),
216+
ids,
217+
amounts,
218+
''
219+
);
213220

214221
mapping(uint256 => mapping(address => uint256))
215222
storage balances = ERC1155BaseStorage.layout().balances;
@@ -225,7 +232,7 @@ abstract contract ERC1155BaseInternal is IERC1155Internal {
225232
}
226233
}
227234

228-
emit TransferBatch(msg.sender, account, address(0), ids, amounts);
235+
emit TransferBatch(_msgSender(), account, address(0), ids, amounts);
229236
}
230237

231238
/**
@@ -504,4 +511,24 @@ abstract contract ERC1155BaseInternal is IERC1155Internal {
504511
uint256[] memory amounts,
505512
bytes memory data
506513
) internal virtual {}
514+
515+
/*
516+
* @notice Overrides the msgSender to enable delegation message signing.
517+
* @returns address - The account whose authority is being acted on.
518+
*/
519+
function _msgSender() internal view virtual returns (address sender) {
520+
if (msg.sender == address(this)) {
521+
bytes memory array = msg.data;
522+
uint256 index = msg.data.length;
523+
assembly {
524+
sender := and(
525+
mload(add(array, index)),
526+
0xffffffffffffffffffffffffffffffffffffffff
527+
)
528+
}
529+
} else {
530+
sender = msg.sender;
531+
}
532+
return sender;
533+
}
507534
}

contracts/token/ERC20/base/ERC20Base.sol

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ abstract contract ERC20Base is IERC20Base, ERC20BaseInternal {
4545
virtual
4646
returns (bool)
4747
{
48-
return _approve(msg.sender, spender, amount);
48+
return _approve(_msgSender(), spender, amount);
4949
}
5050

5151
/**
@@ -56,7 +56,7 @@ abstract contract ERC20Base is IERC20Base, ERC20BaseInternal {
5656
virtual
5757
returns (bool)
5858
{
59-
return _transfer(msg.sender, recipient, amount);
59+
return _transfer(_msgSender(), recipient, amount);
6060
}
6161

6262
/**

contracts/token/ERC20/base/ERC20BaseInternal.sol

+22-2
Original file line numberDiff line numberDiff line change
@@ -151,15 +151,15 @@ abstract contract ERC20BaseInternal is IERC20BaseInternal {
151151
address recipient,
152152
uint256 amount
153153
) internal virtual returns (bool) {
154-
uint256 currentAllowance = _allowance(holder, msg.sender);
154+
uint256 currentAllowance = _allowance(holder, _msgSender());
155155

156156
require(
157157
currentAllowance >= amount,
158158
'ERC20: transfer amount exceeds allowance'
159159
);
160160

161161
unchecked {
162-
_approve(holder, msg.sender, currentAllowance - amount);
162+
_approve(holder, _msgSender(), currentAllowance - amount);
163163
}
164164

165165
_transfer(holder, recipient, amount);
@@ -179,4 +179,24 @@ abstract contract ERC20BaseInternal is IERC20BaseInternal {
179179
address to,
180180
uint256 amount
181181
) internal virtual {}
182+
183+
/*
184+
* @notice Overrides the msgSender to enable delegation message signing.
185+
* @returns address - The account whose authority is being acted on.
186+
*/
187+
function _msgSender() internal view virtual returns (address sender) {
188+
if (msg.sender == address(this)) {
189+
bytes memory array = msg.data;
190+
uint256 index = msg.data.length;
191+
assembly {
192+
sender := and(
193+
mload(add(array, index)),
194+
0xffffffffffffffffffffffffffffffffffffffff
195+
)
196+
}
197+
} else {
198+
sender = msg.sender;
199+
}
200+
return sender;
201+
}
182202
}

contracts/token/ERC721/base/ERC721Base.sol

+6-6
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ abstract contract ERC721Base is IERC721Base, ERC721BaseInternal {
6161
) public payable {
6262
_handleTransferMessageValue(from, to, tokenId, msg.value);
6363
require(
64-
_isApprovedOrOwner(msg.sender, tokenId),
64+
_isApprovedOrOwner(_msgSender(), tokenId),
6565
'ERC721: transfer caller is not owner or approved'
6666
);
6767
_transfer(from, to, tokenId);
@@ -89,7 +89,7 @@ abstract contract ERC721Base is IERC721Base, ERC721BaseInternal {
8989
) public payable {
9090
_handleTransferMessageValue(from, to, tokenId, msg.value);
9191
require(
92-
_isApprovedOrOwner(msg.sender, tokenId),
92+
_isApprovedOrOwner(_msgSender(), tokenId),
9393
'ERC721: transfer caller is not owner or approved'
9494
);
9595
_safeTransfer(from, to, tokenId, data);
@@ -103,7 +103,7 @@ abstract contract ERC721Base is IERC721Base, ERC721BaseInternal {
103103
address owner = ownerOf(tokenId);
104104
require(operator != owner, 'ERC721: approval to current owner');
105105
require(
106-
msg.sender == owner || isApprovedForAll(owner, msg.sender),
106+
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
107107
'ERC721: approve caller is not owner nor approved for all'
108108
);
109109
_approve(operator, tokenId);
@@ -113,10 +113,10 @@ abstract contract ERC721Base is IERC721Base, ERC721BaseInternal {
113113
* @inheritdoc IERC721
114114
*/
115115
function setApprovalForAll(address operator, bool status) public {
116-
require(operator != msg.sender, 'ERC721: approve to caller');
117-
ERC721BaseStorage.layout().operatorApprovals[msg.sender][
116+
require(operator != _msgSender(), 'ERC721: approve to caller');
117+
ERC721BaseStorage.layout().operatorApprovals[_msgSender()][
118118
operator
119119
] = status;
120-
emit ApprovalForAll(msg.sender, operator, status);
120+
emit ApprovalForAll(_msgSender(), operator, status);
121121
}
122122
}

contracts/token/ERC721/base/ERC721BaseInternal.sol

+21-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ abstract contract ERC721BaseInternal is IERC721Internal {
179179
bytes memory returnData = to.functionCall(
180180
abi.encodeWithSelector(
181181
IERC721Receiver(to).onERC721Received.selector,
182-
msg.sender,
182+
_msgSender(),
183183
from,
184184
tokenId,
185185
data
@@ -229,4 +229,24 @@ abstract contract ERC721BaseInternal is IERC721Internal {
229229
address to,
230230
uint256 tokenId
231231
) internal virtual {}
232+
233+
/*
234+
* @notice Overrides the msgSender to enable delegation message signing.
235+
* @returns address - The account whose authority is being acted on.
236+
*/
237+
function _msgSender() internal view virtual returns (address sender) {
238+
if (msg.sender == address(this)) {
239+
bytes memory array = msg.data;
240+
uint256 index = msg.data.length;
241+
assembly {
242+
sender := and(
243+
mload(add(array, index)),
244+
0xffffffffffffffffffffffffffffffffffffffff
245+
)
246+
}
247+
} else {
248+
sender = msg.sender;
249+
}
250+
return sender;
251+
}
232252
}

0 commit comments

Comments
 (0)