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 1 commit
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 testSelfDestructAndCreateAgainCollision() public {
ClementWalter marked this conversation as resolved.
Show resolved Hide resolved
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 @@ namespace Internals {
// 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 ();
}

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