Skip to content

Commit

Permalink
new(test): a couple of account resurrection tests (#488)
Browse files Browse the repository at this point in the history
* start working on recreate

* add re-creation

* test_double_kill

* split blocks differently

* fix(tests): tox, parameterization

* changelog

---------

Co-authored-by: Mario Vega <[email protected]>
  • Loading branch information
yperbasis and marioevz authored Apr 2, 2024
1 parent 5e64f50 commit e738983
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Test fixtures for use by clients are available for each release on the [Github r

### 🧪 Test Cases

- ✨ Add `test_double_kill` and `test_recreate` which test resurrection of accounts killed with `SELFDESTRUCT` ([#488](https://github.com/ethereum/execution-spec-tests/pull/488)).

### 🛠️ Framework

- 🐞 Fix incorrect `!=` operator for `FixedSizeBytes` ([#477](https://github.com/ethereum/execution-spec-tests/pull/477)).
Expand Down
3 changes: 3 additions & 0 deletions tests/constantinople/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""
Test cases for EVM functionality introduced in Constantinople.
"""
5 changes: 5 additions & 0 deletions tests/constantinople/create2/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""
abstract: Test [EIP-1014: Skinny CREATE2](https://eips.ethereum.org/EIPS/eip-1014)
Tests for [EIP-1014: Skinny CREATE2](https://eips.ethereum.org/EIPS/eip-1014).
"""
112 changes: 112 additions & 0 deletions tests/constantinople/create2/test_recreate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
"""
Test Account Self-destruction and Re-creation
"""

import pytest

from ethereum_test_forks import Fork
from ethereum_test_tools import Account, Block, BlockchainTestFiller, Environment, Initcode
from ethereum_test_tools import Opcodes as Op
from ethereum_test_tools import TestAddress, Transaction, Yul, compute_create2_address


@pytest.mark.parametrize("recreate_on_separate_block", [True, False])
@pytest.mark.valid_from("Constantinople")
@pytest.mark.valid_until("Shanghai")
def test_recreate(
blockchain_test: BlockchainTestFiller, fork: Fork, recreate_on_separate_block: bool
):
"""
Test that the storage is cleared when a contract is first destructed then re-created using
CREATE2.
"""
env = Environment()

creator_address = 0x100
creator_contract_code = Op.CALLDATACOPY(0, 0, Op.CALLDATASIZE) + Op.CREATE2(
0, 0, Op.CALLDATASIZE, 0
)

pre = {
TestAddress: Account(balance=1000000000000000000000),
creator_address: Account(
code=creator_contract_code,
nonce=1,
),
}

deploy_code = Yul(
"""
{
switch callvalue()
case 0 {
selfdestruct(0)
}
default {
sstore(0, callvalue())
}
}
""",
fork=fork,
)

initcode = Initcode(deploy_code=deploy_code)

create_tx = Transaction(
nonce=0,
gas_limit=100000000,
to=creator_address,
data=initcode,
)

created_contract_address = compute_create2_address(
address=creator_address, salt=0, initcode=initcode
)

set_storage_tx = Transaction(
nonce=1,
gas_limit=100000000,
to=created_contract_address,
value=1,
)

blocks = [Block(txs=[create_tx, set_storage_tx])]

destruct_tx = Transaction(
nonce=2,
gas_limit=100000000,
to=created_contract_address,
value=0,
)

balance = 1
send_funds_tx = Transaction(
nonce=3,
gas_limit=100000000,
to=created_contract_address,
value=balance,
)

re_create_tx = Transaction(
nonce=4,
gas_limit=100000000,
to=creator_address,
data=initcode,
)

if recreate_on_separate_block:
blocks.append(Block(txs=[destruct_tx, send_funds_tx]))
blocks.append(Block(txs=[re_create_tx]))
else:
blocks.append(Block(txs=[destruct_tx, send_funds_tx, re_create_tx]))

post = {
created_contract_address: Account(
nonce=1,
balance=balance,
code=deploy_code,
storage={},
),
}

blockchain_test(genesis_environment=env, pre=pre, post=post, blocks=blocks)
66 changes: 66 additions & 0 deletions tests/frontier/opcodes/test_selfdestruct.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""
Test the SELFDESTRUCT opcode.
"""

import pytest

from ethereum_test_tools import Account, Block, BlockchainTestFiller, Environment, Initcode
from ethereum_test_tools import Opcodes as Op
from ethereum_test_tools import TestAddress, Transaction, compute_create_address


@pytest.mark.valid_from("Frontier")
@pytest.mark.valid_until("Homestead")
def test_double_kill(blockchain_test: BlockchainTestFiller):
"""
Test that when two transactions attempt to destruct a contract,
the second transaction actually resurrects the contract as an empty account (prior to Spurious
Dragon).
"""
env = Environment()
pre = {
TestAddress: Account(balance=1000000000000000000000),
}

deploy_code = Op.SELFDESTRUCT(Op.ADDRESS)

initcode = Initcode(deploy_code=deploy_code)

create_tx = Transaction(
nonce=0,
gas_limit=100000000,
protected=False,
to=None,
data=initcode,
)

created_contract_address = compute_create_address(address=TestAddress, nonce=0)

block_1 = Block(txs=[create_tx])

first_kill = Transaction(
nonce=1,
gas_limit=100000000,
protected=False,
to=created_contract_address,
)

second_kill = Transaction(
nonce=2,
gas_limit=100000000,
protected=False,
to=created_contract_address,
)

block_2 = Block(txs=[first_kill, second_kill])

post = {
created_contract_address: Account(
nonce=0,
balance=0,
code=b"",
storage={},
),
}

blockchain_test(genesis_environment=env, pre=pre, post=post, blocks=[block_1, block_2])

0 comments on commit e738983

Please sign in to comment.