mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 19:00:46 +00:00
core: remove duplication
This commit is contained in:
parent
478fe9e825
commit
407839baec
3 changed files with 52 additions and 279 deletions
|
|
@ -463,56 +463,6 @@ func TestEIP2780RecipientOOG(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestEIP2780AuthOOG pins the atomic authorization charge point: a later
|
||||
// authorization OOG reverts an earlier successful authorization too.
|
||||
func TestEIP2780AuthOOG(t *testing.T) {
|
||||
a0, authority0 := signAuth(t, authKeyA, delegate8037, 0)
|
||||
key, _ := crypto.GenerateKey()
|
||||
a1, err := types.SignSetCode(key, types.SetCodeAuthorization{
|
||||
ChainID: *uint256.MustFromBig(cfg8037.ChainID), Address: delegate8037, Nonce: 0,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
authority1 := crypto.PubkeyToAddress(key.PublicKey)
|
||||
to := common.HexToAddress("0xe0a0000000000000000000000000000000000009")
|
||||
intrinsic := params.TxBaseCost2780 + params.ColdAccountAccessAmsterdam + 2*params.RegularPerAuthBaseCost
|
||||
gas := intrinsic + params.AccountWriteAmsterdam + authWorstState
|
||||
sdb := mkState(senderAlloc(types.GenesisAlloc{to: {Balance: big.NewInt(1)}}))
|
||||
res, gp, err := applyMsg(t, sdb, setCodeTxGas(0, to, 0, gas, []types.SetCodeAuthorization{a0, a1}))
|
||||
if err != nil || res.Err != vm.ErrOutOfGas {
|
||||
t.Fatalf("result=%v err=%v, want included OOG", res, err)
|
||||
}
|
||||
for _, authority := range []common.Address{authority0, authority1} {
|
||||
if len(sdb.GetCode(authority)) != 0 || sdb.GetNonce(authority) != 0 {
|
||||
t.Fatalf("authority %x persisted after authorization OOG", authority)
|
||||
}
|
||||
}
|
||||
if gp.cumulativeState != 0 || gp.cumulativeRegular != gas {
|
||||
t.Fatalf("gas = <%d,%d>, want <%d,0>", gp.cumulativeRegular, gp.cumulativeState, gas)
|
||||
}
|
||||
}
|
||||
|
||||
// TestEIP2780AuthRevert distinguishes an EVM REVERT from a pre-frame OOG:
|
||||
// state paid by a successful authorization precedes the frame and persists.
|
||||
func TestEIP2780AuthRevert(t *testing.T) {
|
||||
auth, authority := signAuth(t, authKeyA, delegate8037, 0)
|
||||
reverter := common.HexToAddress("0xbad0000000000000000000000000000000000003")
|
||||
sdb := mkState(senderAlloc(types.GenesisAlloc{
|
||||
reverter: {Code: []byte{0x60, 0x00, 0x60, 0x00, 0xfd}},
|
||||
}))
|
||||
res, gp, err := applyMsg(t, sdb, setCodeTxGas(0, reverter, 0, 1_000_000, []types.SetCodeAuthorization{auth}))
|
||||
if err != nil || res.Err != vm.ErrExecutionReverted {
|
||||
t.Fatalf("result=%v err=%v, want execution revert", res, err)
|
||||
}
|
||||
if len(sdb.GetCode(authority)) == 0 || sdb.GetNonce(authority) != 1 {
|
||||
t.Fatalf("authorization not retained after revert: code=%x nonce=%d", sdb.GetCode(authority), sdb.GetNonce(authority))
|
||||
}
|
||||
if gp.cumulativeState != authWorstState {
|
||||
t.Fatalf("state gas = %d, want %d", gp.cumulativeState, authWorstState)
|
||||
}
|
||||
}
|
||||
|
||||
// TestEIP2780SelfTransferDelegated verifies that a self-transfer incurs no
|
||||
// recipient touch or value charges, while resolving the sender's own
|
||||
// delegation is still paid for.
|
||||
|
|
@ -648,72 +598,19 @@ func TestEIP2780RecipientRefill(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestEIP2780ValueEffects checks the observable value-transfer behavior along
|
||||
// with the decomposition's special treatment of self and creation transfers.
|
||||
func TestEIP2780ValueEffects(t *testing.T) {
|
||||
recipient := common.HexToAddress("0xbeef000000000000000000000000000000000006")
|
||||
sdb := mkState(senderAlloc(nil))
|
||||
before := sdb.GetBalance(senderAddr).ToBig()
|
||||
tx := callTx(0, recipient, 7, 300_000, nil)
|
||||
res, _, err := applyMsg(t, sdb, tx)
|
||||
// TestEIP2780Coinbase keeps the intrinsic recipient charge separate from the
|
||||
// runtime warmth of the coinbase account: calling the coinbase directly is
|
||||
// still charged at the cold rate. The warm rate for a coinbase delegation
|
||||
// target is covered by TestEIP2780DelegationWarmth.
|
||||
func TestEIP2780Coinbase(t *testing.T) {
|
||||
coinbase := common.HexToAddress("0xc01ba5e000000000000000000000000000000001")
|
||||
res, gp, err := applyMsgCoinbase(t, mkState(senderAlloc(nil)), callTx(0, coinbase, 0, 100_000, nil), coinbase)
|
||||
if err != nil || res.Err != nil {
|
||||
t.Fatalf("result=%v err=%v", res, err)
|
||||
}
|
||||
if got := sdb.GetBalance(recipient).ToBig(); got.Cmp(big.NewInt(7)) != 0 {
|
||||
t.Fatalf("recipient balance = %v, want 7", got)
|
||||
if want := params.TxBaseCost2780 + params.ColdAccountAccessAmsterdam; gp.cumulativeRegular != want {
|
||||
t.Fatalf("regular gas = %d, want %d", gp.cumulativeRegular, want)
|
||||
}
|
||||
if got := sdb.GetBalance(senderAddr).ToBig(); got.Cmp(new(big.Int).Sub(before, big.NewInt(7))) != 0 {
|
||||
t.Fatalf("sender balance = %v, want value transfer", got)
|
||||
}
|
||||
logs := sdb.GetLogs(common.Hash{}, 0, common.Hash{}, 0)
|
||||
if len(logs) != 1 || logs[0].Topics[0] != params.EthTransferLogEvent {
|
||||
t.Fatalf("logs = %+v, want one EIP-7708 transfer", logs)
|
||||
}
|
||||
|
||||
// A self transfer is not a value move and emits no transfer log.
|
||||
sdb = mkState(senderAlloc(nil))
|
||||
before = sdb.GetBalance(senderAddr).ToBig()
|
||||
tx = callTx(0, senderAddr, 7, 100_000, nil)
|
||||
res, _, err = applyMsg(t, sdb, tx)
|
||||
if err != nil || res.Err != nil {
|
||||
t.Fatalf("self result=%v err=%v", res, err)
|
||||
}
|
||||
logs = sdb.GetLogs(common.Hash{}, 0, common.Hash{}, 0)
|
||||
if sdb.GetBalance(senderAddr).Cmp(uint256.MustFromBig(before)) != 0 || len(logs) != 0 {
|
||||
t.Fatalf("self transfer changed balance or emitted logs: balance=%v logs=%+v", sdb.GetBalance(senderAddr), logs)
|
||||
}
|
||||
}
|
||||
|
||||
// TestEIP2780Coinbase keeps the intrinsic recipient charge separate from the
|
||||
// runtime warmth of the coinbase account.
|
||||
func TestEIP2780Coinbase(t *testing.T) {
|
||||
const (
|
||||
base = params.TxBaseCost2780
|
||||
cold = params.ColdAccountAccessAmsterdam
|
||||
warm = params.WarmAccountAccessAmsterdam
|
||||
)
|
||||
coinbase := common.HexToAddress("0xc01ba5e000000000000000000000000000000001")
|
||||
t.Run("recipient", func(t *testing.T) {
|
||||
res, gp, err := applyMsgCoinbase(t, mkState(senderAlloc(nil)), callTx(0, coinbase, 0, 100_000, nil), coinbase)
|
||||
if err != nil || res.Err != nil {
|
||||
t.Fatalf("result=%v err=%v", res, err)
|
||||
}
|
||||
if gp.cumulativeRegular != base+cold {
|
||||
t.Fatalf("regular gas = %d, want %d", gp.cumulativeRegular, base+cold)
|
||||
}
|
||||
})
|
||||
t.Run("target", func(t *testing.T) {
|
||||
delegated := common.HexToAddress("0xde1e000000000000000000000000000000000007")
|
||||
res, gp, err := applyMsgCoinbase(t, mkState(senderAlloc(types.GenesisAlloc{
|
||||
delegated: {Code: types.AddressToDelegation(coinbase)},
|
||||
})), callTx(0, delegated, 0, 100_000, nil), coinbase)
|
||||
if err != nil || res.Err != nil {
|
||||
t.Fatalf("result=%v err=%v", res, err)
|
||||
}
|
||||
if gp.cumulativeRegular != base+cold+warm {
|
||||
t.Fatalf("regular gas = %d, want %d", gp.cumulativeRegular, base+cold+warm)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestEIP2780DelegationWarmth adds the special targets which are warm before
|
||||
|
|
|
|||
|
|
@ -276,24 +276,6 @@ func TestBALEmptyBlockExcludesCoinbase(t *testing.T) {
|
|||
assertAbsent(t, b, coinbase)
|
||||
}
|
||||
|
||||
// TestBALCoinbaseTipCapturesBalance: positive priority fee credits coinbase
|
||||
// and the balance change appears in the BAL.
|
||||
func TestBALCoinbaseTipCapturesBalance(t *testing.T) {
|
||||
coinbase := common.Address{0xc0}
|
||||
to := common.HexToAddress("0xabba")
|
||||
env := newBALTestEnv(nil)
|
||||
|
||||
b, _ := env.run(t, func(g *BlockGen) {
|
||||
g.SetCoinbase(coinbase)
|
||||
g.AddTx(env.tx(0, &to, big.NewInt(0), params.TxGas, 2 /* gwei tip */, nil))
|
||||
})
|
||||
|
||||
cb := assertPresent(t, b, coinbase)
|
||||
if len(cb.BalanceChanges) == 0 || cb.BalanceChanges[0].PostBalance.Sign() == 0 {
|
||||
t.Fatalf("coinbase missing positive balance change: %+v", cb.BalanceChanges)
|
||||
}
|
||||
}
|
||||
|
||||
// TestBALCoinbasePerTxBalance checks that fee-recipient balances are recorded
|
||||
// after each transaction, rather than only once at the end of the block.
|
||||
func TestBALCoinbasePerTxBalance(t *testing.T) {
|
||||
|
|
@ -718,28 +700,6 @@ func TestBALDelegationTargetOOG(t *testing.T) {
|
|||
|
||||
// ============================== Storage inclusion ==============================
|
||||
|
||||
// TestBALStorageWriteRecorded: SSTORE places the slot in storage_changes and
|
||||
// keeps it out of storage_reads.
|
||||
func TestBALStorageWriteRecorded(t *testing.T) {
|
||||
contract := common.HexToAddress("0xc1")
|
||||
slot := common.BigToHash(big.NewInt(0x01))
|
||||
// PUSH1 0x42 PUSH1 0x01 SSTORE STOP
|
||||
code := []byte{0x60, 0x42, 0x60, 0x01, 0x55, 0x00}
|
||||
env := newBALTestEnv(types.GenesisAlloc{contract: {Code: code, Balance: common.Big0}})
|
||||
|
||||
b, _ := env.run(t, func(g *BlockGen) {
|
||||
g.AddTx(env.tx(0, &contract, big.NewInt(0), 1_000_000, 0, nil))
|
||||
})
|
||||
|
||||
aa := assertPresent(t, b, contract)
|
||||
if !hasStorageWrite(b, contract, slot) {
|
||||
t.Fatalf("expected slot 0x01 in storage_changes\n%s", b.PrettyPrint())
|
||||
}
|
||||
if hasSlotIn(aa.StorageReads, slot) {
|
||||
t.Fatalf("slot 0x01 must NOT appear in storage_reads")
|
||||
}
|
||||
}
|
||||
|
||||
// TestBALStorageSloadOnly: SLOAD without a write puts the slot in storage_reads.
|
||||
func TestBALStorageSloadOnly(t *testing.T) {
|
||||
contract := common.HexToAddress("0xc1")
|
||||
|
|
@ -2128,84 +2088,50 @@ func TestBALDelegatedCallStorage(t *testing.T) {
|
|||
assertEmpty(t, assertPresent(t, b, implementation))
|
||||
}
|
||||
|
||||
// TestBALDelegatedDelegateCallStorage checks the other storage context:
|
||||
// DELEGATECALL to a delegated authority still executes the resolved code
|
||||
// against the original caller's storage.
|
||||
func TestBALDelegatedDelegateCallStorage(t *testing.T) {
|
||||
// TestBALDelegatedCallFamilyStorage checks the storage context of the CALL
|
||||
// family against a delegated authority: the resolved implementation supplies
|
||||
// code only, while the storage read belongs to the executing context — the
|
||||
// authority for CALL/STATICCALL, the caller for DELEGATECALL/CALLCODE.
|
||||
func TestBALDelegatedCallFamilyStorage(t *testing.T) {
|
||||
caller := common.HexToAddress("0xca11")
|
||||
authority := common.HexToAddress("0xa7702")
|
||||
implementation := common.HexToAddress("0x1a11")
|
||||
slot := common.BigToHash(big.NewInt(0x07))
|
||||
implCode := []byte{0x60, 0x07, 0x54, 0x50, 0x00} // SLOAD(7), POP, STOP
|
||||
env := newBALTestEnv(types.GenesisAlloc{
|
||||
caller: {Code: makeStubCaller(0xf4 /* DELEGATECALL */, authority), Balance: common.Big0},
|
||||
authority: {Code: types.AddressToDelegation(implementation), Balance: common.Big0},
|
||||
implementation: {Code: implCode, Balance: common.Big0},
|
||||
})
|
||||
|
||||
b, _ := env.run(t, func(g *BlockGen) {
|
||||
g.AddTx(env.tx(0, &caller, big.NewInt(0), 1_000_000, 0, nil))
|
||||
})
|
||||
|
||||
callerAccess := assertPresent(t, b, caller)
|
||||
if !hasSlotIn(callerAccess.StorageReads, slot) {
|
||||
t.Fatalf("delegated DELEGATECALL read must belong to caller\n%s", b.PrettyPrint())
|
||||
cases := []struct {
|
||||
name string
|
||||
op byte
|
||||
readOwner common.Address
|
||||
}{
|
||||
{"call", 0xf1, authority},
|
||||
{"callcode", 0xf2, caller},
|
||||
{"delegatecall", 0xf4, caller},
|
||||
{"staticcall", 0xfa, authority},
|
||||
}
|
||||
assertEmpty(t, assertPresent(t, b, authority))
|
||||
assertEmpty(t, assertPresent(t, b, implementation))
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
env := newBALTestEnv(types.GenesisAlloc{
|
||||
caller: {Code: makeStubCaller(tc.op, authority), Balance: common.Big0},
|
||||
authority: {Code: types.AddressToDelegation(implementation), Balance: common.Big0},
|
||||
implementation: {Code: implCode, Balance: common.Big0},
|
||||
})
|
||||
|
||||
// TestBALDelegatedStaticCallStorage covers STATICCALL's context. It resolves
|
||||
// the authority's implementation code, but SLOAD remains attached to the static
|
||||
// call target's storage.
|
||||
func TestBALDelegatedStaticCallStorage(t *testing.T) {
|
||||
caller := common.HexToAddress("0xca11")
|
||||
authority := common.HexToAddress("0xa7702")
|
||||
implementation := common.HexToAddress("0x1a11")
|
||||
slot := common.BigToHash(big.NewInt(0x07))
|
||||
implCode := []byte{0x60, 0x07, 0x54, 0x50, 0x00} // SLOAD(7), POP, STOP
|
||||
env := newBALTestEnv(types.GenesisAlloc{
|
||||
caller: {Code: makeStubCaller(0xfa /* STATICCALL */, authority), Balance: common.Big0},
|
||||
authority: {Code: types.AddressToDelegation(implementation), Balance: common.Big0},
|
||||
implementation: {Code: implCode, Balance: common.Big0},
|
||||
})
|
||||
b, _ := env.run(t, func(g *BlockGen) {
|
||||
g.AddTx(env.tx(0, &caller, big.NewInt(0), 1_000_000, 0, nil))
|
||||
})
|
||||
|
||||
b, _ := env.run(t, func(g *BlockGen) {
|
||||
g.AddTx(env.tx(0, &caller, big.NewInt(0), 1_000_000, 0, nil))
|
||||
})
|
||||
|
||||
authorityAccess := assertPresent(t, b, authority)
|
||||
if !hasSlotIn(authorityAccess.StorageReads, slot) {
|
||||
t.Fatalf("delegated STATICCALL read must belong to authority\n%s", b.PrettyPrint())
|
||||
owner := assertPresent(t, b, tc.readOwner)
|
||||
if !hasSlotIn(owner.StorageReads, slot) {
|
||||
t.Fatalf("%s read must belong to %x\n%s", tc.name, tc.readOwner, b.PrettyPrint())
|
||||
}
|
||||
for _, other := range []common.Address{caller, authority} {
|
||||
if other != tc.readOwner {
|
||||
assertEmpty(t, assertPresent(t, b, other))
|
||||
}
|
||||
}
|
||||
assertEmpty(t, assertPresent(t, b, implementation))
|
||||
})
|
||||
}
|
||||
assertEmpty(t, assertPresent(t, b, implementation))
|
||||
}
|
||||
|
||||
// TestBALDelegatedCallCodeStorage covers CALLCODE's storage context. As with
|
||||
// DELEGATECALL, the implementation address supplies code but is not the owner
|
||||
// of storage reads.
|
||||
func TestBALDelegatedCallCodeStorage(t *testing.T) {
|
||||
caller := common.HexToAddress("0xca11")
|
||||
authority := common.HexToAddress("0xa7702")
|
||||
implementation := common.HexToAddress("0x1a11")
|
||||
slot := common.BigToHash(big.NewInt(0x07))
|
||||
implCode := []byte{0x60, 0x07, 0x54, 0x50, 0x00} // SLOAD(7), POP, STOP
|
||||
env := newBALTestEnv(types.GenesisAlloc{
|
||||
caller: {Code: makeStubCaller(0xf2 /* CALLCODE */, authority), Balance: common.Big0},
|
||||
authority: {Code: types.AddressToDelegation(implementation), Balance: common.Big0},
|
||||
implementation: {Code: implCode, Balance: common.Big0},
|
||||
})
|
||||
|
||||
b, _ := env.run(t, func(g *BlockGen) {
|
||||
g.AddTx(env.tx(0, &caller, big.NewInt(0), 1_000_000, 0, nil))
|
||||
})
|
||||
|
||||
callerAccess := assertPresent(t, b, caller)
|
||||
if !hasSlotIn(callerAccess.StorageReads, slot) {
|
||||
t.Fatalf("delegated CALLCODE read must belong to caller\n%s", b.PrettyPrint())
|
||||
}
|
||||
assertEmpty(t, assertPresent(t, b, authority))
|
||||
assertEmpty(t, assertPresent(t, b, implementation))
|
||||
}
|
||||
|
||||
// TestBALDelegationOneHop verifies that resolving A -> B does not
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ import (
|
|||
// TestEIP8246SelfdestructNoBurn verifies that, once EIP-8246 is active
|
||||
// (Amsterdam), a contract that is created and self-destructs to itself within
|
||||
// the same transaction keeps its balance instead of burning it: the account
|
||||
// survives as a balance-only account (no code, zero nonce, balance preserved).
|
||||
// survives as a balance-only account (no code, zero nonce, balance preserved)
|
||||
// whose storage is cleared at transaction finalization.
|
||||
//
|
||||
// https://eips.ethereum.org/EIPS/eip-8246
|
||||
func TestEIP8246SelfdestructNoBurn(t *testing.T) {
|
||||
|
|
@ -42,9 +43,11 @@ func TestEIP8246SelfdestructNoBurn(t *testing.T) {
|
|||
signer = types.LatestSigner(&config)
|
||||
engine = beacon.New(ethash.NewFaker())
|
||||
value = big.NewInt(1_000_000)
|
||||
// Init code: ADDRESS (0x30) ; SELFDESTRUCT (0xff). The created contract
|
||||
// self-destructs to itself during its own creation transaction.
|
||||
initcode = common.FromHex("30ff")
|
||||
slot = common.BigToHash(big.NewInt(0x05))
|
||||
// Init code: SSTORE(5, 0x2a); ADDRESS (0x30); SELFDESTRUCT (0xff). The
|
||||
// created contract stores a value and self-destructs to itself during
|
||||
// its own creation transaction.
|
||||
initcode = []byte{0x60, 0x2a, 0x60, 0x05, 0x55, 0x30, 0xff}
|
||||
)
|
||||
// TODO: drop this hacky Amsterdam config initialization once the final
|
||||
// Amsterdam config is available (mirrors TestEthTransferLogs).
|
||||
|
|
@ -99,61 +102,8 @@ func TestEIP8246SelfdestructNoBurn(t *testing.T) {
|
|||
if got := state.GetCodeSize(created); got != 0 {
|
||||
t.Errorf("created account code size = %d, want 0 (code must be cleared)", got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestEIP8246SelfdestructClearsStorage verifies the other half of the
|
||||
// balance-only-account rule: a same-transaction selfdestruct preserves balance
|
||||
// but clears storage during transaction finalization.
|
||||
func TestEIP8246SelfdestructClearsStorage(t *testing.T) {
|
||||
var (
|
||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
sender = crypto.PubkeyToAddress(key.PublicKey)
|
||||
config = *params.MergedTestChainConfig
|
||||
signer = types.LatestSigner(&config)
|
||||
engine = beacon.New(ethash.NewFaker())
|
||||
value = big.NewInt(1_000_000)
|
||||
slot = common.BigToHash(big.NewInt(0x05))
|
||||
stored = common.BigToHash(big.NewInt(0x2a))
|
||||
created = crypto.CreateAddress(sender, 0)
|
||||
)
|
||||
config.AmsterdamTime = new(uint64)
|
||||
gspec := &Genesis{
|
||||
Config: &config,
|
||||
Alloc: types.GenesisAlloc{sender: {Balance: newGwei(1_000_000_000)}},
|
||||
}
|
||||
// SSTORE(5, 0x2a); ADDRESS; SELFDESTRUCT.
|
||||
initcode := []byte{0x60, 0x2a, 0x60, 0x05, 0x55, 0x30, 0xff}
|
||||
db, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(_ int, b *BlockGen) {
|
||||
b.AddTx(types.MustSignNewTx(key, signer, &types.DynamicFeeTx{
|
||||
ChainID: gspec.Config.ChainID,
|
||||
Nonce: 0,
|
||||
Gas: 1_000_000,
|
||||
GasFeeCap: newGwei(5),
|
||||
GasTipCap: newGwei(5),
|
||||
Value: value,
|
||||
Data: initcode,
|
||||
}))
|
||||
})
|
||||
chain, err := NewBlockChain(db, gspec, engine, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create chain: %v", err)
|
||||
}
|
||||
defer chain.Stop()
|
||||
state, err := chain.StateAt(blocks[0].Header())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to obtain block state: %v", err)
|
||||
}
|
||||
if got := state.GetBalance(created).ToBig(); got.Cmp(value) != 0 {
|
||||
t.Errorf("created balance = %v, want %v", got, value)
|
||||
}
|
||||
if got := state.GetNonce(created); got != 0 {
|
||||
t.Errorf("created nonce = %d, want 0", got)
|
||||
}
|
||||
if got := state.GetCodeSize(created); got != 0 {
|
||||
t.Errorf("created code size = %d, want 0", got)
|
||||
}
|
||||
if got := state.GetState(created, slot); got != (common.Hash{}) {
|
||||
t.Errorf("created storage slot %x = %x, want 0 (stored %x before selfdestruct)", slot, got, stored)
|
||||
t.Errorf("created storage slot %x = %x, want 0 (storage must be cleared)", slot, got)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue