Skip to content
This repository has been archived by the owner on Jan 9, 2025. It is now read-only.

Fix bytecode is not written when starknet contract already exists #822

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
4 changes: 2 additions & 2 deletions scripts/utils/kakarot.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,12 +415,12 @@ async def store_bytecode(bytecode: Union[str, bytes], **kwargs):
)
assert success
starknet_address, evm_address = response
stored_bytecode = await get_bytecode(evm_address)
stored_bytecode = await eth_get_code(evm_address)
assert stored_bytecode == bytecode
return evm_address


async def get_bytecode(address: Union[int, str]):
async def eth_get_code(address: Union[int, str]):
starknet_address = await compute_starknet_address(address)
return bytes(
(
Expand Down
34 changes: 26 additions & 8 deletions solidity_contracts/tests/PlainOpcodes.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,35 @@ contract PlainOpcodesTest is Test {
assert(keccak256(bytes(errorMessage)) == keccak256("FAIL"));
}

function testSelfDestructAndCreateAgain() public {
function testSelfDestructAndCreateAgainCollisionAfterKill() public {
bytes memory bytecode = type(ContractWithSelfdestructMethod).creationCode;
uint256 salt = 1234;
address addr = plainOpcodes.create2(bytecode, salt);
ContractWithSelfdestructMethod contract_ = ContractWithSelfdestructMethod(addr);
contract_.inc();
address _address_0;
assembly {
_address_0 := create2(0, add(bytecode, 32), mload(bytecode), salt)
}
ContractWithSelfdestructMethod contract_ = ContractWithSelfdestructMethod(_address_0);
contract_.kill();
plainOpcodes.create2(bytecode, salt);
contract_.inc();
uint256 count = contract_.count();
assertEq(count, 2);
address _address_1;
assembly {
_address_1 := create2(0, add(bytecode, 32), mload(bytecode), salt)
}
assertEq(_address_1, address(0));
}

function testCreate2CollisionReturnsZeroAddress() public {
bytes memory bytecode = type(ContractWithSelfdestructMethod).creationCode;
uint256 salt = 1234;
address _address_0;
assembly {
_address_0 := create2(0, add(bytecode, 32), mload(bytecode), salt)
}
assertGt(uint160(_address_0), 0);
address _address_1;
assembly {
_address_1 := create2(0, add(bytecode, 32), mload(bytecode), salt)
}
assertEq(_address_1, address(0));
}

function testCreate() public {
Expand Down
7 changes: 7 additions & 0 deletions src/data_availability/starknet.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,13 @@
// Save storages
Internals._save_storage(starknet_address, self.storage_start, self.storage);

// Update bytecode if required (SELFDESTRUCTed contract, redeployed)
let (bytecode_len) = IAccount.bytecode_len(starknet_address);
if (bytecode_len != self.code_len) {
IContractAccount.write_bytecode(starknet_address, self.code_len, self.code);
return ();

Check warning on line 180 in src/data_availability/starknet.cairo

View check run for this annotation

Codecov / codecov/patch

src/data_availability/starknet.cairo#L177-L180

Added lines #L177 - L180 were not covered by tests
}

return ();
}

Expand Down
34 changes: 34 additions & 0 deletions tests/end_to_end/PlainOpcodes/test_plain_opcodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,40 @@ async def test_should_create_counter_and_invoke_in_the_same_tx(
assert await counter.count() == 1

class TestCreate2:
async def test_should_redeploy_after_selfdestruct(
self,
plain_opcodes,
get_solidity_contract,
owner,
eth_get_code,
):
contract_with_selfdestruct = get_solidity_contract(
"PlainOpcodes", "ContractWithSelfdestructMethod"
)
salt = 12345
receipt = await plain_opcodes.create2(
bytecode=contract_with_selfdestruct.constructor().data_in_transaction,
salt=salt,
caller_eoa=owner.starknet_contract,
)
events = plain_opcodes.events.parse_starknet_events(receipt.events)
assert len(events["Create2Address"]) == 1
contract_with_selfdestruct = get_solidity_contract(
"PlainOpcodes",
"ContractWithSelfdestructMethod",
address=events["Create2Address"][0]["_address"],
)
assert await eth_get_code(contract_with_selfdestruct.address)
await contract_with_selfdestruct.kill()
assert not await eth_get_code(contract_with_selfdestruct.address)

await plain_opcodes.create2(
bytecode=contract_with_selfdestruct.constructor().data_in_transaction,
salt=salt,
caller_eoa=owner.starknet_contract,
)
assert await eth_get_code(contract_with_selfdestruct.address)

async def test_should_deploy_bytecode_at_address(
self,
plain_opcodes,
Expand Down
10 changes: 10 additions & 0 deletions tests/end_to_end/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,13 @@ def eth_send_transaction(max_fee, owner):
return partial(
eth_send_transaction, max_fee=max_fee, caller_eoa=owner.starknet_contract
)


@pytest.fixture
def eth_get_code():
"""
Send a decoded transaction to Kakarot.
"""
from scripts.utils.kakarot import eth_get_code

return eth_get_code
Loading