Make ERC2771Context return original sender address if msg.data.length <= 20 (#4481)
(cherry picked from commit 28d9ac2bdb)
This commit is contained in:
committed by
Francisco Giordano
parent
d26025b410
commit
7ec712baa5
5
.changeset/unlucky-beans-obey.md
Normal file
5
.changeset/unlucky-beans-obey.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'openzeppelin-solidity': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
`ERC2771Context`: Return the forwarder address whenever the `msg.data` of a call originating from a trusted forwarder is not long enough to contain the request signer address (i.e. `msg.data.length` is less than 20 bytes), as specified by ERC-2771.
|
||||||
@ -22,7 +22,7 @@ abstract contract ERC2771Context is Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _msgSender() internal view virtual override returns (address sender) {
|
function _msgSender() internal view virtual override returns (address sender) {
|
||||||
if (isTrustedForwarder(msg.sender)) {
|
if (isTrustedForwarder(msg.sender) && msg.data.length >= 20) {
|
||||||
// The assembly code is more direct than the Solidity version using `abi.decode`.
|
// The assembly code is more direct than the Solidity version using `abi.decode`.
|
||||||
/// @solidity memory-safe-assembly
|
/// @solidity memory-safe-assembly
|
||||||
assembly {
|
assembly {
|
||||||
|
|||||||
@ -12,6 +12,8 @@ const ContextMockCaller = artifacts.require('ContextMockCaller');
|
|||||||
const { shouldBehaveLikeRegularContext } = require('../utils/Context.behavior');
|
const { shouldBehaveLikeRegularContext } = require('../utils/Context.behavior');
|
||||||
|
|
||||||
contract('ERC2771Context', function (accounts) {
|
contract('ERC2771Context', function (accounts) {
|
||||||
|
const [, anotherAccount] = accounts;
|
||||||
|
|
||||||
beforeEach(async function () {
|
beforeEach(async function () {
|
||||||
this.forwarder = await MinimalForwarder.new();
|
this.forwarder = await MinimalForwarder.new();
|
||||||
this.recipient = await ERC2771ContextMock.new(this.forwarder.address);
|
this.recipient = await ERC2771ContextMock.new(this.forwarder.address);
|
||||||
@ -73,6 +75,15 @@ contract('ERC2771Context', function (accounts) {
|
|||||||
const { tx } = await this.forwarder.execute(req, sign);
|
const { tx } = await this.forwarder.execute(req, sign);
|
||||||
await expectEvent.inTransaction(tx, ERC2771ContextMock, 'Sender', { sender: this.sender });
|
await expectEvent.inTransaction(tx, ERC2771ContextMock, 'Sender', { sender: this.sender });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns the original sender when calldata length is less than 20 bytes (address length)', async function () {
|
||||||
|
// The forwarder doesn't produce calls with calldata length less than 20 bytes
|
||||||
|
const recipient = await ERC2771ContextMock.new(anotherAccount);
|
||||||
|
|
||||||
|
const { receipt } = await recipient.msgSender({ from: anotherAccount });
|
||||||
|
|
||||||
|
await expectEvent(receipt, 'Sender', { sender: anotherAccount });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('msgData', function () {
|
describe('msgData', function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user