Skip to content

Commit 6f1d1b6

Browse files
committed
core/vm: implement EIP-2681: Limit account nonce to 2^64-1 (ethereum#23853)
1 parent 7aeb9bd commit 6f1d1b6

File tree

4 files changed

+20
-9
lines changed

4 files changed

+20
-9
lines changed

core/error.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ var (
3737
// next one expected based on the local chain.
3838
ErrNonceTooHigh = errors.New("nonce too high")
3939

40+
// ErrNonceMax is returned if the nonce of a transaction sender account has
41+
// maximum allowed value and would become invalid if incremented.
42+
ErrNonceMax = errors.New("nonce has max value")
43+
4044
ErrNotXDPoS = errors.New("XDPoS not found in config")
4145

4246
ErrNotFoundM1 = errors.New("list M1 not found ")

core/state_transition.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -197,16 +197,19 @@ func (st *StateTransition) buyGas() error {
197197
}
198198

199199
func (st *StateTransition) preCheck() error {
200-
msg := st.msg
201-
sender := st.from()
202-
203200
// Make sure this transaction's nonce is correct
204-
if msg.CheckNonce() {
205-
nonce := st.state.GetNonce(sender.Address())
206-
if nonce < msg.Nonce() {
207-
return ErrNonceTooHigh
208-
} else if nonce > msg.Nonce() {
209-
return ErrNonceTooLow
201+
if st.msg.CheckNonce() {
202+
// Make sure this transaction's nonce is correct.
203+
stNonce := st.state.GetNonce(st.from().Address())
204+
if msgNonce := st.msg.Nonce(); stNonce < msgNonce {
205+
return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooHigh,
206+
st.msg.From().Hex(), msgNonce, stNonce)
207+
} else if stNonce > msgNonce {
208+
return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooLow,
209+
st.msg.From().Hex(), msgNonce, stNonce)
210+
} else if stNonce+1 < stNonce {
211+
return fmt.Errorf("%w: address %v, nonce: %d", ErrNonceMax,
212+
st.msg.From().Hex(), stNonce)
210213
}
211214
}
212215
return st.buyGas()

core/vm/errors.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ var (
3434
ErrWriteProtection = errors.New("write protection")
3535
ErrReturnDataOutOfBounds = errors.New("return data out of bounds")
3636
ErrGasUintOverflow = errors.New("gas uint64 overflow")
37+
ErrNonceUintOverflow = errors.New("nonce uint64 overflow")
3738

3839
// errStopToken is an internal token indicating interpreter loop termination,
3940
// never returned to outside callers.

core/vm/evm.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,9 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
443443
return nil, common.Address{}, gas, ErrInsufficientBalance
444444
}
445445
nonce := evm.StateDB.GetNonce(caller.Address())
446+
if nonce+1 < nonce {
447+
return nil, common.Address{}, gas, ErrNonceUintOverflow
448+
}
446449
evm.StateDB.SetNonce(caller.Address(), nonce+1)
447450
// We add this to the access list _before_ taking a snapshot. Even if the creation fails,
448451
// the access-list change should not be rolled back

0 commit comments

Comments
 (0)