Skip to content

Commit

Permalink
SELFDESTRUCT must reset contract account (#3067)
Browse files Browse the repository at this point in the history
* test: SELFDESTRUCT must reset contract account

* update frontier pin

* fix rust test

* Revert "fix rust test"

This reverts commit c12604a.

* update frontier pin

* Update test/contracts/src/SelfDestruct.sol

Co-authored-by: Ahmad Kaouk <[email protected]>

---------

Co-authored-by: Ahmad Kaouk <[email protected]>
  • Loading branch information
RomarQ and ahmadkaouk authored Dec 3, 2024
1 parent c69c0cb commit 99eebab
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 26 deletions.
52 changes: 26 additions & 26 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 53 additions & 0 deletions test/contracts/src/SelfDestruct.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.24;

contract SelfDestructable {
constructor() {
selfdestruct(payable(address(0)));
}
}

contract SelfDestructAfterCreate2 {
uint constant SALT = 1;

address public deployed1;
address public deployed2;

function step1() public {
bytes memory bytecode = type(SelfDestructable).creationCode;
address contractAddress;
uint contractSize;
assembly {
contractAddress := create2(0, add(bytecode, 32), mload(bytecode), SALT)
contractSize := extcodesize(contractAddress)
}
require(contractSize == 0, "Contract size should be zero");
deployed1 = contractAddress;
}


function step2() public {
bytes memory bytecode = type(SelfDestructable).creationCode;
address contractAddress;
uint contractSize;
assembly {
contractAddress := create2(0, add(bytecode, 32), mload(bytecode), SALT)
contractSize := extcodesize(contractAddress)
}
require(contractSize == 0, "Contract size should be zero");
deployed2 = contractAddress;
require(deployed1 == deployed2, "Addresses not equal");
}

function cannotRecreateInTheSameCall() public {
bytes memory bytecode = type(SelfDestructable).creationCode;
address contractAddress1;
address contractAddress2;
assembly {
contractAddress1 := create2(0, add(bytecode, 32), mload(bytecode), SALT)
contractAddress2 := create2(0, add(bytecode, 32), mload(bytecode), SALT)
}
require(contractAddress1 != address(0), "First address must not be null");
require(contractAddress2 == address(0), "Second address must be null");
}
}
82 changes: 82 additions & 0 deletions test/suites/dev/moonbase/test-contract/test-self-destruct.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { describeSuite, expect } from "@moonwall/cli";
import { createEthersTransaction } from "@moonwall/util";
import { encodeFunctionData } from "viem";

describeSuite({
id: "D010613",
title: "Test self-destruct contract",
foundationMethods: "dev",
testCases: ({ context, it }) => {
it({
id: "T01",
title: "SELFDESTRUCT must reset contract account",
test: async function () {
const { contractAddress, abi } = await context.deployContract!("SelfDestructAfterCreate2");

const block = await context.createBlock([
await createEthersTransaction(context, {
to: contractAddress,
data: encodeFunctionData({
abi,
functionName: "step1",
args: [],
}),
gasLimit: 100_000n,
nonce: 1,
}),
await createEthersTransaction(context, {
to: contractAddress,
data: encodeFunctionData({
abi,
functionName: "step2",
args: [],
}),
gasLimit: 100_000n,
nonce: 2,
}),
await createEthersTransaction(context, {
to: contractAddress,
data: encodeFunctionData({
abi,
functionName: "cannotRecreateInTheSameCall",
args: [],
}),
gasLimit: 100_000n,
nonce: 3,
}),
]);

for (const result of block.result) {
const receipt = await context
.viem("public")
.getTransactionReceipt({ hash: result.hash as `0x${string}` });

expect(receipt.status).toBe("success");
}

const deployedAddress = await context.readContract!({
contractName: "SelfDestructAfterCreate2",
contractAddress: contractAddress,
functionName: "deployed1",
args: [],
rawTxOnly: true,
});

const deletedAccount = await context.polkadotJs().query.system.account(deployedAddress);
expect(deletedAccount.toJSON()).toEqual(
expect.objectContaining({
nonce: 0,
consumers: 0,
providers: 0,
sufficients: 0,
data: expect.objectContaining({
free: 0,
reserved: 0,
frozen: 0,
}),
})
);
},
});
},
});

0 comments on commit 99eebab

Please sign in to comment.