Skip to content

Commit 70ab1fa

Browse files
authored
fix(pkg/userop): unmarshal empty fields as zero-initialized (#466)
1 parent b6546fe commit 70ab1fa

File tree

2 files changed

+99
-26
lines changed

2 files changed

+99
-26
lines changed

pkg/userop/userop.go

Lines changed: 76 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -159,47 +159,97 @@ func (op *UserOperation) UnmarshalJSON(data []byte) error {
159159

160160
var err error
161161
op.Sender = common.HexToAddress(uoDTO.Sender)
162-
if nonceBI, ok := big.NewInt(0).SetString(uoDTO.Nonce, 0); !ok {
163-
return fmt.Errorf("invalid nonce: %w", err)
162+
163+
if uoDTO.Nonce == "" {
164+
op.Nonce = decimal.NewFromInt(0)
164165
} else {
165-
op.Nonce = decimal.NewFromBigInt(nonceBI, 0)
166+
if nonceBI, ok := big.NewInt(0).SetString(uoDTO.Nonce, 0); !ok {
167+
return fmt.Errorf("invalid nonce: %w", err)
168+
} else {
169+
op.Nonce = decimal.NewFromBigInt(nonceBI, 0)
170+
}
166171
}
167-
if op.InitCode, err = hexutil.Decode(uoDTO.InitCode); err != nil {
168-
return fmt.Errorf("invalid initCode: %w", err)
172+
173+
if uoDTO.InitCode == "" {
174+
op.InitCode = []byte{}
175+
} else {
176+
if op.InitCode, err = hexutil.Decode(uoDTO.InitCode); err != nil {
177+
return fmt.Errorf("invalid initCode: %w", err)
178+
}
169179
}
170-
if op.CallData, err = hexutil.Decode(uoDTO.CallData); err != nil {
171-
return fmt.Errorf("invalid callData: %w", err)
180+
181+
if uoDTO.CallData == "" {
182+
op.CallData = []byte{}
183+
} else {
184+
if op.CallData, err = hexutil.Decode(uoDTO.CallData); err != nil {
185+
return fmt.Errorf("invalid callData: %w", err)
186+
}
172187
}
173-
if callGasLimitBI, ok := new(big.Int).SetString(uoDTO.CallGasLimit, 0); !ok {
174-
return fmt.Errorf("invalid callGasLimit: %w", err)
188+
189+
if uoDTO.CallGasLimit == "" {
190+
op.CallGasLimit = decimal.NewFromInt(0)
175191
} else {
176-
op.CallGasLimit = decimal.NewFromBigInt(callGasLimitBI, 0)
192+
if callGasLimitBI, ok := new(big.Int).SetString(uoDTO.CallGasLimit, 0); !ok {
193+
return fmt.Errorf("invalid callGasLimit: %w", err)
194+
} else {
195+
op.CallGasLimit = decimal.NewFromBigInt(callGasLimitBI, 0)
196+
}
177197
}
178-
if verificationGasLimitBI, ok := new(big.Int).SetString(uoDTO.VerificationGasLimit, 0); !ok {
179-
return fmt.Errorf("invalid verificationGasLimit: %w", err)
198+
199+
if uoDTO.VerificationGasLimit == "" {
200+
op.VerificationGasLimit = decimal.NewFromInt(0)
180201
} else {
181-
op.VerificationGasLimit = decimal.NewFromBigInt(verificationGasLimitBI, 0)
202+
if verificationGasLimitBI, ok := new(big.Int).SetString(uoDTO.VerificationGasLimit, 0); !ok {
203+
return fmt.Errorf("invalid verificationGasLimit: %w", err)
204+
} else {
205+
op.VerificationGasLimit = decimal.NewFromBigInt(verificationGasLimitBI, 0)
206+
}
182207
}
183-
if preVerificationGasBI, ok := new(big.Int).SetString(uoDTO.PreVerificationGas, 0); !ok {
184-
return fmt.Errorf("invalid preVerificationGas: %w", err)
208+
209+
if uoDTO.PreVerificationGas == "" {
210+
op.PreVerificationGas = decimal.NewFromInt(0)
185211
} else {
186-
op.PreVerificationGas = decimal.NewFromBigInt(preVerificationGasBI, 0)
212+
if preVerificationGasBI, ok := new(big.Int).SetString(uoDTO.PreVerificationGas, 0); !ok {
213+
return fmt.Errorf("invalid preVerificationGas: %w", err)
214+
} else {
215+
op.PreVerificationGas = decimal.NewFromBigInt(preVerificationGasBI, 0)
216+
}
187217
}
188-
if maxFeePerGasBI, ok := new(big.Int).SetString(uoDTO.MaxFeePerGas, 0); !ok {
189-
return fmt.Errorf("invalid maxFeePerGas: %w", err)
218+
219+
if uoDTO.MaxFeePerGas == "" {
220+
op.MaxFeePerGas = decimal.NewFromInt(0)
190221
} else {
191-
op.MaxFeePerGas = decimal.NewFromBigInt(maxFeePerGasBI, 0)
222+
if maxFeePerGasBI, ok := new(big.Int).SetString(uoDTO.MaxFeePerGas, 0); !ok {
223+
return fmt.Errorf("invalid maxFeePerGas: %w", err)
224+
} else {
225+
op.MaxFeePerGas = decimal.NewFromBigInt(maxFeePerGasBI, 0)
226+
}
192227
}
193-
if maxPriorityFeePerGasBI, ok := new(big.Int).SetString(uoDTO.MaxPriorityFeePerGas, 0); !ok {
194-
return fmt.Errorf("invalid maxPriorityFeePerGas: %w", err)
228+
229+
if uoDTO.MaxPriorityFeePerGas == "" {
230+
op.MaxPriorityFeePerGas = decimal.NewFromInt(0)
195231
} else {
196-
op.MaxPriorityFeePerGas = decimal.NewFromBigInt(maxPriorityFeePerGasBI, 0)
232+
if maxPriorityFeePerGasBI, ok := new(big.Int).SetString(uoDTO.MaxPriorityFeePerGas, 0); !ok {
233+
return fmt.Errorf("invalid maxPriorityFeePerGas: %w", err)
234+
} else {
235+
op.MaxPriorityFeePerGas = decimal.NewFromBigInt(maxPriorityFeePerGasBI, 0)
236+
}
197237
}
198-
if op.PaymasterAndData, err = hexutil.Decode(uoDTO.PaymasterAndData); err != nil {
199-
return fmt.Errorf("invalid paymasterAndData: %w", err)
238+
239+
if uoDTO.PaymasterAndData == "" {
240+
op.PaymasterAndData = []byte{}
241+
} else {
242+
if op.PaymasterAndData, err = hexutil.Decode(uoDTO.PaymasterAndData); err != nil {
243+
return fmt.Errorf("invalid paymasterAndData: %w", err)
244+
}
200245
}
201-
if op.Signature, err = hexutil.Decode(uoDTO.Signature); err != nil {
202-
return fmt.Errorf("invalid signature: %w", err)
246+
247+
if uoDTO.Signature == "" {
248+
op.Signature = []byte{}
249+
} else {
250+
if op.Signature, err = hexutil.Decode(uoDTO.Signature); err != nil {
251+
return fmt.Errorf("invalid signature: %w", err)
252+
}
203253
}
204254

205255
return nil

pkg/userop/userop_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,29 @@ func TestUnmarshal(t *testing.T) {
9191
assert.Equal(t, userOpDTO.PaymasterAndData, hexutil.Encode(userOp.PaymasterAndData))
9292
assert.Equal(t, userOpDTO.Signature, hexutil.Encode(userOp.Signature))
9393
}
94+
95+
func TestUnmarshalEmpty(t *testing.T) {
96+
userOpDTO := UserOperationDTO{}
97+
98+
userOpBytes, err := json.Marshal(userOpDTO)
99+
require.NoError(t, err)
100+
101+
var userOp UserOperation
102+
err = json.Unmarshal(userOpBytes, &userOp)
103+
require.NoError(t, err)
104+
assert.Equal(t, common.Address{}.String(), userOp.Sender.String())
105+
assert.Equal(t, "0x0", "0x"+userOp.Nonce.BigInt().Text(16))
106+
assert.Equal(t, "0x", hexutil.Encode(userOp.InitCode))
107+
assert.Equal(t, "0x", hexutil.Encode(userOp.CallData))
108+
assert.Equal(t, "0x0", "0x"+userOp.CallGasLimit.BigInt().Text(16))
109+
assert.Equal(t, "0x0", "0x"+userOp.VerificationGasLimit.BigInt().Text(16))
110+
assert.Equal(t, "0x0", "0x"+userOp.PreVerificationGas.BigInt().Text(16))
111+
assert.Equal(t, "0x0", "0x"+userOp.MaxFeePerGas.BigInt().Text(16))
112+
assert.Equal(t, "0x0", "0x"+userOp.MaxPriorityFeePerGas.BigInt().Text(16))
113+
assert.Equal(t, "0x", hexutil.Encode(userOp.PaymasterAndData))
114+
assert.Equal(t, "0x", hexutil.Encode(userOp.Signature))
115+
}
116+
94117
func TestDeepCopy(t *testing.T) {
95118
initCode, err := hexutil.Decode("0xbeefdead")
96119
require.NoError(t, err)

0 commit comments

Comments
 (0)