Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new(test): a couple of account resurrection tests #488

Merged
merged 7 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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])
Loading