Adjust ERC2771Context._msgData for msg.data.length < 20 (#4484)
This commit is contained in:
5
.changeset/warm-guests-rule.md
Normal file
5
.changeset/warm-guests-rule.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'openzeppelin-solidity': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
`ERC2771Context`: Prevent revert in `_msgData()` when 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). Return the full calldata in that case.
|
||||||
@ -34,7 +34,7 @@ abstract contract ERC2771Context is Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _msgData() internal view virtual override returns (bytes calldata) {
|
function _msgData() internal view virtual override returns (bytes calldata) {
|
||||||
if (isTrustedForwarder(msg.sender)) {
|
if (isTrustedForwarder(msg.sender) && msg.data.length >= 20) {
|
||||||
return msg.data[:msg.data.length - 20];
|
return msg.data[:msg.data.length - 20];
|
||||||
} else {
|
} else {
|
||||||
return super._msgData();
|
return super._msgData();
|
||||||
|
|||||||
@ -16,6 +16,12 @@ contract ContextMock is Context {
|
|||||||
function msgData(uint256 integerValue, string memory stringValue) public {
|
function msgData(uint256 integerValue, string memory stringValue) public {
|
||||||
emit Data(_msgData(), integerValue, stringValue);
|
emit Data(_msgData(), integerValue, stringValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event DataShort(bytes data);
|
||||||
|
|
||||||
|
function msgDataShort() public {
|
||||||
|
emit DataShort(_msgData());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contract ContextMockCaller {
|
contract ContextMockCaller {
|
||||||
|
|||||||
@ -12,7 +12,7 @@ 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;
|
const [, trustedForwarder] = accounts;
|
||||||
|
|
||||||
const MAX_UINT48 = web3.utils.toBN(1).shln(48).subn(1).toString();
|
const MAX_UINT48 = web3.utils.toBN(1).shln(48).subn(1).toString();
|
||||||
|
|
||||||
@ -84,11 +84,11 @@ contract('ERC2771Context', function (accounts) {
|
|||||||
|
|
||||||
it('returns the original sender when calldata length is less than 20 bytes (address length)', async function () {
|
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
|
// The forwarder doesn't produce calls with calldata length less than 20 bytes
|
||||||
const recipient = await ERC2771ContextMock.new(anotherAccount);
|
const recipient = await ERC2771ContextMock.new(trustedForwarder);
|
||||||
|
|
||||||
const { receipt } = await recipient.msgSender({ from: anotherAccount });
|
const { receipt } = await recipient.msgSender({ from: trustedForwarder });
|
||||||
|
|
||||||
await expectEvent(receipt, 'Sender', { sender: anotherAccount });
|
await expectEvent(receipt, 'Sender', { sender: trustedForwarder });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -117,5 +117,15 @@ contract('ERC2771Context', function (accounts) {
|
|||||||
await expectEvent.inTransaction(tx, ERC2771ContextMock, 'Data', { data, integerValue, stringValue });
|
await expectEvent.inTransaction(tx, ERC2771ContextMock, 'Data', { data, integerValue, stringValue });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns the full original data 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(trustedForwarder);
|
||||||
|
|
||||||
|
const { receipt } = await recipient.msgDataShort({ from: trustedForwarder });
|
||||||
|
|
||||||
|
const data = recipient.contract.methods.msgDataShort().encodeABI();
|
||||||
|
await expectEvent(receipt, 'DataShort', { data });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user