Skip to content

Commit 6087a18

Browse files
committed
support msg.value in ECDSAMetaTransactionContext
1 parent 054d056 commit 6087a18

File tree

3 files changed

+20
-6
lines changed

3 files changed

+20
-6
lines changed

contracts/meta/_ECDSAMetaTransactionContext.sol

+11-6
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ abstract contract _ECDSAMetaTransactionContext is
1414
using ECDSA for bytes32;
1515

1616
bytes32 internal constant EIP_712_TYPE_HASH =
17-
keccak256('ECDSAMetaTransaction(bytes msgData,uint256 nonce)');
17+
keccak256(
18+
'ECDSAMetaTransaction(bytes msgData,uint256 msgValue,uint256 nonce)'
19+
);
1820

1921
bytes32
2022
internal constant ECDSA_META_TRANSACTION_CONTEXT_TRANSIENT_STORAGE_SLOT =
@@ -139,11 +141,16 @@ abstract contract _ECDSAMetaTransactionContext is
139141
unchecked {
140142
bytes calldata msgData = msg.data[:split];
141143
uint256 nonce = uint256(bytes32(msg.data[split:split + 32]));
144+
bytes calldata signature = msg.data[split + 32:];
142145

143-
// TODO: include msg.sender in hash to restrict forwarder
144-
// TODO: include msg.value
146+
// TODO: include msg.sender in hash to restrict forwarder?
145147
bytes32 structHash = keccak256(
146-
abi.encode(EIP_712_TYPE_HASH, keccak256(msgData), nonce)
148+
abi.encode(
149+
EIP_712_TYPE_HASH,
150+
keccak256(msgData),
151+
msg.value,
152+
nonce
153+
)
147154
);
148155

149156
bytes32 domainSeparator = EIP712.calculateDomainSeparator_01100();
@@ -176,8 +183,6 @@ abstract contract _ECDSAMetaTransactionContext is
176183
signedHash := keccak256(pointer, 66)
177184
}
178185

179-
bytes calldata signature = msg.data[split + 32:];
180-
181186
// TODO: see what happens if split calldata v r s
182187
address signer = signedHash.tryRecover(signature);
183188

lib/erc20_permit.ts

+3
Original file line numberDiff line numberDiff line change
@@ -107,19 +107,22 @@ const signECDSAMetaTransaction = async (
107107
instance: IERC5267,
108108
signer: SignerWithAddress,
109109
msgData: BytesLike,
110+
msgValue: bigint,
110111
nonce: bigint,
111112
): Promise<Signature> => {
112113
const domain = await getDomain(instance);
113114

114115
const types = {
115116
ECDSAMetaTransaction: [
116117
{ name: 'msgData', type: 'bytes' },
118+
{ name: 'msgValue', type: 'uint256' },
117119
{ name: 'nonce', type: 'uint256' },
118120
],
119121
};
120122

121123
const values = {
122124
msgData,
125+
msgValue,
123126
nonce,
124127
};
125128

test/meta/ECDSAMetaTransactionContext.ts

+6
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,20 @@ describe('ECDSAMetaTransactionContext', () => {
4343

4444
// TODO: test multiple calls in same tx to validate that transient storage is used correctly
4545

46+
// TODO: test msg.value revert cases
47+
4648
describe('__internal', () => {
4749
describe('#_msgSender()', () => {
4850
it('returns signer if signature is valid', async () => {
4951
const data = instance.$_msgSender.fragment.selector;
5052
const nonce = 1n;
53+
const value = 0n;
5154

5255
const signature = await signECDSAMetaTransaction(
5356
instance,
5457
signer,
5558
data,
59+
value,
5660
nonce,
5761
);
5862

@@ -94,11 +98,13 @@ describe('ECDSAMetaTransactionContext', () => {
9498
it('returns message data without suffix if signature is valid', async () => {
9599
const nonSuffixedData = instance.$_msgData.fragment.selector;
96100
const nonce = 1n;
101+
const value = 0n;
97102

98103
const signature = await signECDSAMetaTransaction(
99104
instance,
100105
signer,
101106
nonSuffixedData,
107+
value,
102108
nonce,
103109
);
104110

0 commit comments

Comments
 (0)