Skip to content

Commit 6c93a45

Browse files
committed
expand _Context to _MetaTransactionContext
1 parent 9a0af0a commit 6c93a45

File tree

3 files changed

+67
-44
lines changed

3 files changed

+67
-44
lines changed

contracts/utils/_Context.sol

+2-44
Original file line numberDiff line numberDiff line change
@@ -7,49 +7,7 @@ import { _IContext } from './_IContext.sol';
77
* @title Utility contract for supporting alternative authorization schemes
88
*/
99
abstract contract _Context is _IContext {
10-
/*
11-
* @notice Returns the intended sender of a message. Either msg.sender or the address of the authorizing signer.
12-
* Enables MetaTransactions, since the sender doesn't need to be the tx.origin or even the msg.sender.
13-
* @returns address - The account whose authority is being acted on.
14-
* and the end-user for GSN relayed calls (where msg.sender is actually `RelayHub`).
15-
*
16-
* IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.sender`, and use {_msgSender} instead.
17-
*/
18-
function _msgSender() internal view virtual returns (address sender) {
19-
if (msg.sender == address(this)) {
20-
return _getRelayedCallSender();
21-
} else {
22-
sender = msg.sender;
23-
}
24-
return sender;
25-
}
26-
27-
function _getRelayedCallSender()
28-
private
29-
pure
30-
returns (address payable result)
31-
{
32-
// We need to read 20 bytes (an address) located at array index msg.data.length - 20. In memory, the array
33-
// is prefixed with a 32-byte length value, so we first add 32 to get the memory read index. However, doing
34-
// so would leave the address in the upper 20 bytes of the 32-byte word, which is inconvenient and would
35-
// require bit shifting. We therefore subtract 12 from the read index so the address lands on the lower 20
36-
// bytes. This can always be done due to the 32-byte prefix.
37-
38-
// The final memory read index is msg.data.length - 20 + 32 - 12 = msg.data.length. Using inline assembly is the
39-
// easiest/most-efficient way to perform this operation.
40-
41-
// These fields are not accessible from assembly
42-
bytes memory array = msg.data;
43-
uint256 index = msg.data.length;
44-
45-
// solhint-disable-next-line no-inline-assembly
46-
assembly {
47-
// Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
48-
result := and(
49-
mload(add(array, index)),
50-
0xffffffffffffffffffffffffffffffffffffffff
51-
)
52-
}
53-
return result;
10+
function _msgSender() internal view virtual returns (address msgSender) {
11+
msgSender = msg.sender;
5412
}
5513
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.20;
4+
5+
import { _IContext } from './_IContext.sol';
6+
7+
interface _IMetaTransactionContext is _IContext {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.20;
4+
5+
import { _Context } from './_Context.sol';
6+
7+
abstract contract _MetaTransactionContext is _Context {
8+
/*
9+
* @notice Returns the intended sender of a message. Either msg.sender or the address of the authorizing signer.
10+
* Enables MetaTransactions, since the sender doesn't need to be the tx.origin or even the msg.sender.
11+
* @returns address - The account whose authority is being acted on.
12+
* and the end-user for GSN relayed calls (where msg.sender is actually `RelayHub`).
13+
*
14+
* IMPORTANT: Contracts derived from {GSNRecipient} should never use `msg.sender`, and use {_msgSender} instead.
15+
*/
16+
function _msgSender()
17+
internal
18+
view
19+
virtual
20+
override
21+
returns (address msgSender)
22+
{
23+
if (msg.sender == address(this)) {
24+
msgSender = _getRelayedCallSender();
25+
} else {
26+
msgSender = msg.sender;
27+
}
28+
}
29+
30+
function _getRelayedCallSender()
31+
private
32+
pure
33+
returns (address payable result)
34+
{
35+
// We need to read 20 bytes (an address) located at array index msg.data.length - 20. In memory, the array
36+
// is prefixed with a 32-byte length value, so we first add 32 to get the memory read index. However, doing
37+
// so would leave the address in the upper 20 bytes of the 32-byte word, which is inconvenient and would
38+
// require bit shifting. We therefore subtract 12 from the read index so the address lands on the lower 20
39+
// bytes. This can always be done due to the 32-byte prefix.
40+
41+
// The final memory read index is msg.data.length - 20 + 32 - 12 = msg.data.length. Using inline assembly is the
42+
// easiest/most-efficient way to perform this operation.
43+
44+
// These fields are not accessible from assembly
45+
bytes memory array = msg.data;
46+
uint256 index = msg.data.length;
47+
48+
// solhint-disable-next-line no-inline-assembly
49+
assembly {
50+
// Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
51+
result := and(
52+
mload(add(array, index)),
53+
0xffffffffffffffffffffffffffffffffffffffff
54+
)
55+
}
56+
return result;
57+
}
58+
}

0 commit comments

Comments
 (0)