diff --git a/src/ethereum/forks/amsterdam/state_tracker.py b/src/ethereum/forks/amsterdam/state_tracker.py index c75eb198f53..ad5f033c97b 100644 --- a/src/ethereum/forks/amsterdam/state_tracker.py +++ b/src/ethereum/forks/amsterdam/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -562,7 +563,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -586,6 +587,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/arrow_glacier/state_tracker.py b/src/ethereum/forks/arrow_glacier/state_tracker.py index f6702729bc2..ed3e97fae8f 100644 --- a/src/ethereum/forks/arrow_glacier/state_tracker.py +++ b/src/ethereum/forks/arrow_glacier/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -555,7 +556,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -579,6 +580,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/berlin/state_tracker.py b/src/ethereum/forks/berlin/state_tracker.py index f6702729bc2..ed3e97fae8f 100644 --- a/src/ethereum/forks/berlin/state_tracker.py +++ b/src/ethereum/forks/berlin/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -555,7 +556,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -579,6 +580,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/bpo1/state_tracker.py b/src/ethereum/forks/bpo1/state_tracker.py index 09348663439..1b1877e101c 100644 --- a/src/ethereum/forks/bpo1/state_tracker.py +++ b/src/ethereum/forks/bpo1/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -542,7 +543,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -566,6 +567,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/bpo2/state_tracker.py b/src/ethereum/forks/bpo2/state_tracker.py index 09348663439..1b1877e101c 100644 --- a/src/ethereum/forks/bpo2/state_tracker.py +++ b/src/ethereum/forks/bpo2/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -542,7 +543,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -566,6 +567,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/bpo3/state_tracker.py b/src/ethereum/forks/bpo3/state_tracker.py index 09348663439..1b1877e101c 100644 --- a/src/ethereum/forks/bpo3/state_tracker.py +++ b/src/ethereum/forks/bpo3/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -542,7 +543,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -566,6 +567,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/bpo4/state_tracker.py b/src/ethereum/forks/bpo4/state_tracker.py index 09348663439..1b1877e101c 100644 --- a/src/ethereum/forks/bpo4/state_tracker.py +++ b/src/ethereum/forks/bpo4/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -542,7 +543,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -566,6 +567,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/bpo5/state_tracker.py b/src/ethereum/forks/bpo5/state_tracker.py index 09348663439..1b1877e101c 100644 --- a/src/ethereum/forks/bpo5/state_tracker.py +++ b/src/ethereum/forks/bpo5/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -542,7 +543,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -566,6 +567,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/byzantium/state_tracker.py b/src/ethereum/forks/byzantium/state_tracker.py index f6702729bc2..ed3e97fae8f 100644 --- a/src/ethereum/forks/byzantium/state_tracker.py +++ b/src/ethereum/forks/byzantium/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -555,7 +556,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -579,6 +580,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/cancun/state_tracker.py b/src/ethereum/forks/cancun/state_tracker.py index 09348663439..1b1877e101c 100644 --- a/src/ethereum/forks/cancun/state_tracker.py +++ b/src/ethereum/forks/cancun/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -542,7 +543,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -566,6 +567,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/constantinople/state_tracker.py b/src/ethereum/forks/constantinople/state_tracker.py index f6702729bc2..ed3e97fae8f 100644 --- a/src/ethereum/forks/constantinople/state_tracker.py +++ b/src/ethereum/forks/constantinople/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -555,7 +556,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -579,6 +580,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/dao_fork/state_tracker.py b/src/ethereum/forks/dao_fork/state_tracker.py index f6702729bc2..ed3e97fae8f 100644 --- a/src/ethereum/forks/dao_fork/state_tracker.py +++ b/src/ethereum/forks/dao_fork/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -555,7 +556,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -579,6 +580,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/frontier/state_tracker.py b/src/ethereum/forks/frontier/state_tracker.py index f6702729bc2..ed3e97fae8f 100644 --- a/src/ethereum/forks/frontier/state_tracker.py +++ b/src/ethereum/forks/frontier/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -555,7 +556,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -579,6 +580,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/gray_glacier/state_tracker.py b/src/ethereum/forks/gray_glacier/state_tracker.py index f6702729bc2..ed3e97fae8f 100644 --- a/src/ethereum/forks/gray_glacier/state_tracker.py +++ b/src/ethereum/forks/gray_glacier/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -555,7 +556,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -579,6 +580,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/homestead/state_tracker.py b/src/ethereum/forks/homestead/state_tracker.py index f6702729bc2..ed3e97fae8f 100644 --- a/src/ethereum/forks/homestead/state_tracker.py +++ b/src/ethereum/forks/homestead/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -555,7 +556,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -579,6 +580,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/istanbul/state_tracker.py b/src/ethereum/forks/istanbul/state_tracker.py index f6702729bc2..ed3e97fae8f 100644 --- a/src/ethereum/forks/istanbul/state_tracker.py +++ b/src/ethereum/forks/istanbul/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -555,7 +556,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -579,6 +580,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/london/state_tracker.py b/src/ethereum/forks/london/state_tracker.py index f6702729bc2..ed3e97fae8f 100644 --- a/src/ethereum/forks/london/state_tracker.py +++ b/src/ethereum/forks/london/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -555,7 +556,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -579,6 +580,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/muir_glacier/state_tracker.py b/src/ethereum/forks/muir_glacier/state_tracker.py index f6702729bc2..ed3e97fae8f 100644 --- a/src/ethereum/forks/muir_glacier/state_tracker.py +++ b/src/ethereum/forks/muir_glacier/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -555,7 +556,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -579,6 +580,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/osaka/state_tracker.py b/src/ethereum/forks/osaka/state_tracker.py index 09348663439..1b1877e101c 100644 --- a/src/ethereum/forks/osaka/state_tracker.py +++ b/src/ethereum/forks/osaka/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -542,7 +543,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -566,6 +567,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/paris/state_tracker.py b/src/ethereum/forks/paris/state_tracker.py index 178ffa0a79f..659e24cebee 100644 --- a/src/ethereum/forks/paris/state_tracker.py +++ b/src/ethereum/forks/paris/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -559,7 +560,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -583,6 +584,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/prague/state_tracker.py b/src/ethereum/forks/prague/state_tracker.py index 09348663439..1b1877e101c 100644 --- a/src/ethereum/forks/prague/state_tracker.py +++ b/src/ethereum/forks/prague/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -542,7 +543,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -566,6 +567,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/shanghai/state_tracker.py b/src/ethereum/forks/shanghai/state_tracker.py index 178ffa0a79f..659e24cebee 100644 --- a/src/ethereum/forks/shanghai/state_tracker.py +++ b/src/ethereum/forks/shanghai/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -559,7 +560,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -583,6 +584,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/spurious_dragon/state_tracker.py b/src/ethereum/forks/spurious_dragon/state_tracker.py index f6702729bc2..ed3e97fae8f 100644 --- a/src/ethereum/forks/spurious_dragon/state_tracker.py +++ b/src/ethereum/forks/spurious_dragon/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -555,7 +556,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -579,6 +580,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/src/ethereum/forks/tangerine_whistle/state_tracker.py b/src/ethereum/forks/tangerine_whistle/state_tracker.py index f6702729bc2..ed3e97fae8f 100644 --- a/src/ethereum/forks/tangerine_whistle/state_tracker.py +++ b/src/ethereum/forks/tangerine_whistle/state_tracker.py @@ -26,6 +26,7 @@ from ethereum_types.numeric import U256, Uint from ethereum.crypto.hash import Hash32, keccak256 +from ethereum.exceptions import InvalidBlock from ethereum.state import ( EMPTY_ACCOUNT, EMPTY_CODE_HASH, @@ -555,7 +556,7 @@ def reduce_sender_balance(sender: Account) -> None: sender.balance -= amount def increase_recipient_balance(recipient: Account) -> None: - recipient.balance += amount + recipient.balance = recipient.balance.wrapping_add(amount) modify_state(tx_state, sender_address, reduce_sender_balance) modify_state(tx_state, recipient_address, increase_recipient_balance) @@ -579,6 +580,8 @@ def create_ether( """ def increase_balance(account: Account) -> None: + if Uint(account.balance) + Uint(amount) > Uint(U256.MAX_VALUE): + raise InvalidBlock("account balance overflow") account.balance += amount modify_state(tx_state, address, increase_balance) diff --git a/tests/frontier/validation/test_recipient_balance_overflow.py b/tests/frontier/validation/test_recipient_balance_overflow.py new file mode 100644 index 00000000000..d6252460571 --- /dev/null +++ b/tests/frontier/validation/test_recipient_balance_overflow.py @@ -0,0 +1,67 @@ +""" +Recipient balance overflow on value transfer. + +when the tx value plus the recipient's current balance would +exceed ``2**256 - 1`` (maximum representable balance), +besu crashes. + +- besu : ``java.lang.ArithmeticException: UInt256 overflow`` is raised + inside ``MessageCallProcessor.transferValue`` (an internal + client error / stack trace, not a clean consensus rule). The + tx and block are rejected. + +- geth / nethermind / erigon / reth : silently wrap the recipient's + balance modulo ``2**256``. The bytecode executes normally and + the transaction settles with the wrapped balance. + +- EELS : behavior adjusted to match geth / nethermind / erigon / reth in this + commit. + +On mainnet the case is unreachable (total ETH supply < 2**256) so it is +more of a theoretical case +""" + +import pytest +from execution_testing import ( + Account, + Alloc, + Environment, + StateTestFiller, + Transaction, +) +from execution_testing.vm import Op + + +@pytest.mark.eels_base_coverage +def test_recipient_balance_overflow( + state_test: StateTestFiller, + pre: Alloc, +) -> None: + """ + Value transfer where ``recipient.balance + tx.value`` exactly equals + ``2**256`` — one wei past the UINT256 ceiling. + + The recipient is a normal contract whose code is a single ``STOP``, + so the only operation that touches the recipient's balance is the + transaction's value transfer. The recipient's balance must wrap to + zero. + """ + sender = pre.fund_eoa() + recipient = pre.deploy_contract( + code=Op.STOP, + balance=2**256 - 2, + ) + + tx = Transaction( + sender=sender, + to=recipient, + value=2, + gas_limit=21_000, + protected=False, + ) + + post = { + recipient: Account(balance=0), + } + + state_test(env=Environment(), pre=pre, post=post, tx=tx)