Skip to content

Commit

Permalink
[evm] add SelfDestruct6780 test (#4509)
Browse files Browse the repository at this point in the history
  • Loading branch information
dustinxie authored Dec 9, 2024
1 parent 31f35a6 commit 5848248
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 13 deletions.
2 changes: 1 addition & 1 deletion action/protocol/execution/protocol_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1331,7 +1331,7 @@ func TestCancunEVM(t *testing.T) {
NewSmartContractTest(t, "testdata-cancun/basefee.json")
})
t.Run("eip6780-selfdestruct", func(t *testing.T) {
t.Skip("TODO: test it ")
NewSmartContractTest(t, "testdata-cancun/selfdestruct.json")
})
}

Expand Down
37 changes: 37 additions & 0 deletions action/protocol/execution/testdata-cancun/selfdestruct.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"initGenesis": {
"isBering" : true,
"isIceland" : true,
"isLondon" : true,
"isShanghai" : true,
"isCancun": true
},
"initBalances": [{
"account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms",
"rawBalance": "1000000000000000000000000000"
}],
"deployments": [{
"rawByteCode": "608060405234801561000f575f80fd5b50335f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102f88061005c5f395ff3fe608060405260043610610037575f3560e01c80630c08bf881461004257806312065fe0146100585780638da5cb5b146100825761003e565b3661003e57005b5f80fd5b34801561004d575f80fd5b506100566100ac565b005b348015610063575f80fd5b5061006c610171565b60405161007991906101b3565b60405180910390f35b34801561008d575f80fd5b50610096610178565b6040516100a3919061020b565b60405180910390f35b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610139576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610130906102a4565b60405180910390fd5b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5f47905090565b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f819050919050565b6101ad8161019b565b82525050565b5f6020820190506101c65f8301846101a4565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6101f5826101cc565b9050919050565b610205816101eb565b82525050565b5f60208201905061021e5f8301846101fc565b92915050565b5f82825260208201905092915050565b7f4f6e6c7920746865206f776e65722063616e2064657374726f792074686520635f8201527f6f6e747261637400000000000000000000000000000000000000000000000000602082015250565b5f61028e602783610224565b915061029982610234565b604082019050919050565b5f6020820190508181035f8301526102bb81610282565b905091905056fea2646970667358221220b78ecca519bda7ff2a88d8d2e964b5eaa98e01e80322cffe2fc97d17b9dcb6e464736f6c63430008180033",
"rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1",
"rawAmount": "0",
"rawGasLimit": 5000000,
"rawGasPrice": "2000000000000",
"rawExpectedGasConsumed": 269559,
"expectedStatus": 1,
"expectedBalances": [],
"comment": "deploy selfdestruct"
}],
"executions": [{
"rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1",
"rawByteCode": "0c08bf88",
"rawAmount": "0",
"rawGasLimit": 1000000,
"rawGasPrice": "2000000000000",
"rawAccessList": [],
"rawExpectedGasConsumed": 17819,
"expectedStatus": 1,
"readOnly": true,
"rawReturnValue": "",
"comment": "call selfdestruct"
}]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

// this is the contract for "_selfdestructOnCreationContract" under blockchain/integrity

contract SelfDestructOnCreation {
address payable public owner;

constructor() payable {
owner = payable(msg.sender); // Set contract deployer as owner
selfdestruct(owner); // Self-destruct the contract immediately, sending any funds to the recipient
}

// Function to check balance of the contract
function getBalance() external view returns (uint256) {
return address(this).balance;
}
}
24 changes: 24 additions & 0 deletions action/protocol/execution/testdata-cancun/selfdestruction.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

contract SelfDestructExample {
address payable public owner;

constructor() {
owner = payable(msg.sender); // Set contract deployer as owner
}

// Function to self-destruct the contract
function terminate() external {
require(msg.sender == owner, "Only the owner can destroy the contract");
selfdestruct(owner); // Send remaining funds to the owner and destroy the contract
}

// Fallback function to receive Ether
receive() external payable {}

// Function to check balance of the contract
function getBalance() external view returns (uint256) {
return address(this).balance;
}
}
83 changes: 73 additions & 10 deletions blockchain/integrity/integrity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import (
"github.com/iotexproject/iotex-core/v2/db/trie/mptrie"
"github.com/iotexproject/iotex-core/v2/pkg/unit"
. "github.com/iotexproject/iotex-core/v2/pkg/util/assertions"
"github.com/iotexproject/iotex-core/v2/pkg/util/blockutil"
"github.com/iotexproject/iotex-core/v2/state"
"github.com/iotexproject/iotex-core/v2/state/factory"
"github.com/iotexproject/iotex-core/v2/test/identityset"
Expand Down Expand Up @@ -926,15 +927,11 @@ func createChain(cfg config.Config, inMem bool) (blockchain.Blockchain, factory.
if dao == nil {
return nil, nil, nil, nil, err
}
ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGas, fakeGetBlockTime)
if err = ep.Register(registry); err != nil {
return nil, nil, nil, nil, err
}
rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding)
if err = rewardingProtocol.Register(registry); err != nil {
return nil, nil, nil, nil, err
}
return blockchain.NewBlockchain(
bc := blockchain.NewBlockchain(
cfg.Chain,
cfg.Genesis,
dao,
Expand All @@ -943,7 +940,23 @@ func createChain(cfg config.Config, inMem bool) (blockchain.Blockchain, factory.
sf,
protocol.NewGenericValidator(sf, accountutil.AccountState),
)),
), sf, dao, ap, nil
)
btc, err := blockutil.NewBlockTimeCalculator(func(uint64) time.Duration { return time.Second },
bc.TipHeight, func(height uint64) (time.Time, error) {
blk, err := dao.GetBlockByHeight(height)
if err != nil {
return time.Time{}, err
}
return blk.Timestamp(), nil
})
if err != nil {
return nil, nil, nil, nil, err
}
ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGas, btc.CalculateBlockTime)
if err = ep.Register(registry); err != nil {
return nil, nil, nil, nil, err
}
return bc, sf, dao, ap, nil
}

func TestBlockchainHardForkFeatures(t *testing.T) {
Expand Down Expand Up @@ -993,7 +1006,7 @@ func TestBlockchainHardForkFeatures(t *testing.T) {
cfg.Genesis.VanuatuBlockHeight = 4
cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(10000000000).String()

ctx := context.Background()
ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis)
bc, sf, dao, ap, err := createChain(cfg, true)
require.NoError(err)
sk, err := iotexcrypto.HexStringToPrivateKey(cfg.Chain.ProducerPrivKey)
Expand Down Expand Up @@ -1232,7 +1245,7 @@ func TestBlockchainHardForkFeatures(t *testing.T) {
require.Equal(v.b, a.Balance.String())
}

// Add block 4 -- test the UseTxContainer and AddClaimRewardAddress flag
// Add block 4 -- test the UseTxContainer, AddClaimRewardAddress, and EIP-6780 selfdestruct
var (
txs [2]*types.Transaction
contractHash hash.Hash256
Expand Down Expand Up @@ -1283,14 +1296,39 @@ func TestBlockchainHardForkFeatures(t *testing.T) {
tsf2, err = action.Sign(elp, priKey0)
require.NoError(err)
require.NoError(ap.Add(ctx, tsf2))
elp = (&action.EnvelopeBuilder{}).SetNonce(7).
SetChainID(cfg.Chain.ID).
SetGasPrice(minGas).
SetGasLimit(500000).
SetAction(action.NewExecution(action.EmptyAddress, new(big.Int), _selfdestructContract)).Build()
ex1, err = action.Sign(elp, priKey0)
require.NoError(err)
require.NoError(ap.Add(ctx, ex1))
elp = (&action.EnvelopeBuilder{}).SetNonce(8).
SetChainID(cfg.Chain.ID).
SetGasPrice(minGas).
SetGasLimit(500000).
SetAction(action.NewExecution(action.EmptyAddress, new(big.Int), _selfdestructOnCreationContract)).Build()
ex2, err = action.Sign(elp, priKey0)
require.NoError(err)
require.NoError(ap.Add(ctx, ex2))
selfdestructContract := "io12fltnfupejreyl8fmd9jq6rcfextg5ra9zjwuz"
elp = (&action.EnvelopeBuilder{}).SetNonce(9).
SetChainID(cfg.Chain.ID).
SetGasPrice(minGas).
SetGasLimit(500000).
SetAction(action.NewExecution(selfdestructContract, new(big.Int), MustNoErrorV(hex.DecodeString("0c08bf88")))).Build()
ex3, err := action.Sign(elp, priKey0)
require.NoError(err)
require.NoError(ap.Add(ctx, ex3))

blockTime = blockTime.Add(time.Second)
blk3, err := bc.MintNewBlock(blockTime)
require.NoError(err)
require.EqualValues(4, blk3.Height())
require.EqualValues(40020, blk3.Header.GasUsed())
require.EqualValues(377122, blk3.Header.GasUsed())
require.EqualValues(action.InitialBaseFee, blk3.Header.BaseFee().Uint64())
require.Equal(4, len(blk3.Body.Actions))
require.Equal(7, len(blk3.Body.Actions))
require.NoError(bc.CommitBlock(blk3))

// verify contract execution
Expand All @@ -1312,6 +1350,31 @@ func TestBlockchainHardForkFeatures(t *testing.T) {
require.EqualValues(1, a.AccountType())
require.Equal("200000000000", a.Balance.String())

// verify EIP-6780 selfdestruct contract address
for _, v := range []struct {
h hash.Hash256
txType string
gas uint64
}{
{MustNoErrorV(ex1.Hash()), "selfdestruct", 269559},
{MustNoErrorV(ex2.Hash()), "selfdestruct-oncreation", 49724},
{MustNoErrorV(ex3.Hash()), "selfdestruct-afterwards", 17819},
} {
r = MustNoErrorV(receiptByActionHash(dao, 4, v.h))
require.EqualValues(1, r.Status)
require.EqualValues(v.gas, r.GasConsumed)
if v.txType == "selfdestruct" {
require.Equal(selfdestructContract, r.ContractAddress)
a = MustNoErrorV(accountutil.AccountState(ctx, sf, MustNoErrorV(address.FromString(r.ContractAddress))))
require.True(a.IsContract())
require.False(a.IsNewbieAccount())
} else if v.txType == "selfdestruct-oncreation" {
a = MustNoErrorV(accountutil.AccountState(ctx, sf, MustNoErrorV(address.FromString(r.ContractAddress))))
require.False(a.IsContract())
require.True(a.IsNewbieAccount())
}
}

// commit 4 blocks to a new chain
testTriePath2, err := testutil.PathOfTempFile("trie")
require.NoError(err)
Expand Down
6 changes: 4 additions & 2 deletions blockchain/integrity/testcontract_test.go

Large diffs are not rendered by default.

0 comments on commit 5848248

Please sign in to comment.