Skip to content

Commit 2e785fa

Browse files
VM/EVM: move selfdestruct type to set (#2806)
* vm/evm: move selfdestruct type to set * evm: selfdestruct updates * vm: fix test runner * vm: fix setting hardfork correctly
1 parent b2df147 commit 2e785fa

File tree

6 files changed

+43
-29
lines changed

6 files changed

+43
-29
lines changed

packages/evm/src/evm.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,7 @@ export class EVM implements EVMInterface {
716716
this.journal
717717
)
718718
if (message.selfdestruct) {
719-
interpreter._result.selfdestruct = message.selfdestruct as { [key: string]: Uint8Array }
719+
interpreter._result.selfdestruct = message.selfdestruct
720720
}
721721
if (message.createdAddresses) {
722722
interpreter._result.createdAddresses = message.createdAddresses
@@ -738,7 +738,7 @@ export class EVM implements EVMInterface {
738738
result = {
739739
...result,
740740
logs: [],
741-
selfdestruct: {},
741+
selfdestruct: new Set(),
742742
createdAddresses: new Set(),
743743
}
744744
}
@@ -798,7 +798,7 @@ export class EVM implements EVMInterface {
798798
isCompiled: opts.isCompiled,
799799
isStatic: opts.isStatic,
800800
salt: opts.salt,
801-
selfdestruct: opts.selfdestruct ?? {},
801+
selfdestruct: opts.selfdestruct ?? new Set(),
802802
createdAddresses: opts.createdAddresses ?? new Set(),
803803
delegatecall: opts.delegatecall,
804804
versionedHashes: opts.versionedHashes,
@@ -868,7 +868,7 @@ export class EVM implements EVMInterface {
868868
// (this only happens the Frontier/Chainstart fork)
869869
// then the error is dismissed
870870
if (err && err.error !== ERROR.CODESTORE_OUT_OF_GAS) {
871-
result.execResult.selfdestruct = {}
871+
result.execResult.selfdestruct = new Set()
872872
result.execResult.createdAddresses = new Set()
873873
result.execResult.gasRefund = BigInt(0)
874874
}
@@ -914,7 +914,7 @@ export class EVM implements EVMInterface {
914914
caller: opts.caller,
915915
value: opts.value,
916916
depth: opts.depth,
917-
selfdestruct: opts.selfdestruct ?? {},
917+
selfdestruct: opts.selfdestruct ?? new Set(),
918918
isStatic: opts.isStatic,
919919
versionedHashes: opts.versionedHashes,
920920
})
@@ -1073,9 +1073,9 @@ export interface ExecResult {
10731073
*/
10741074
logs?: Log[]
10751075
/**
1076-
* A map from the accounts that have self-destructed to the addresses to send their funds to
1076+
* A set of accounts to selfdestruct
10771077
*/
1078-
selfdestruct?: { [k: string]: Uint8Array }
1078+
selfdestruct?: Set<string>
10791079
/**
10801080
* Map of addresses which were created (used in EIP 6780)
10811081
*/

packages/evm/src/interpreter.ts

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ export interface RunResult {
2929
logs: Log[]
3030
returnValue?: Uint8Array
3131
/**
32-
* A map from the accounts that have self-destructed to the addresses to send their funds to
32+
* A set of accounts to selfdestruct
3333
*/
34-
selfdestruct: { [k: string]: Uint8Array }
34+
selfdestruct: Set<string>
3535

3636
/**
3737
* A map which tracks which addresses were created (used in EIP 6780)
@@ -160,7 +160,7 @@ export class Interpreter {
160160
this._result = {
161161
logs: [],
162162
returnValue: undefined,
163-
selfdestruct: {},
163+
selfdestruct: new Set(),
164164
}
165165
}
166166

@@ -840,7 +840,7 @@ export class Interpreter {
840840
}
841841

842842
async _baseCall(msg: Message): Promise<bigint> {
843-
const selfdestruct = { ...this._result.selfdestruct }
843+
const selfdestruct = new Set(this._result.selfdestruct)
844844
msg.selfdestruct = selfdestruct
845845
msg.gasRefund = this._runState.gasRefund
846846

@@ -882,7 +882,9 @@ export class Interpreter {
882882
}
883883

884884
if (!results.execResult.exceptionError) {
885-
Object.assign(this._result.selfdestruct, selfdestruct)
885+
for (const addressToSelfdestructHex of selfdestruct) {
886+
this._result.selfdestruct.add(addressToSelfdestructHex)
887+
}
886888
if (this._common.isActivatedEIP(6780)) {
887889
// copy over the items to result via iterator
888890
for (const item of createdAddresses!) {
@@ -910,7 +912,7 @@ export class Interpreter {
910912
data: Uint8Array,
911913
salt?: Uint8Array
912914
): Promise<bigint> {
913-
const selfdestruct = { ...this._result.selfdestruct }
915+
const selfdestruct = new Set(this._result.selfdestruct)
914916
const caller = this._env.address
915917
const depth = this._env.depth + 1
916918

@@ -954,6 +956,12 @@ export class Interpreter {
954956
versionedHashes: this._env.versionedHashes,
955957
})
956958

959+
let createdAddresses: Set<string>
960+
if (this._common.isActivatedEIP(6780)) {
961+
createdAddresses = new Set(this._result.createdAddresses)
962+
message.createdAddresses = createdAddresses
963+
}
964+
957965
const results = await this._evm.runCall({ message })
958966

959967
if (results.execResult.logs) {
@@ -975,7 +983,15 @@ export class Interpreter {
975983
!results.execResult.exceptionError ||
976984
results.execResult.exceptionError.error === ERROR.CODESTORE_OUT_OF_GAS
977985
) {
978-
Object.assign(this._result.selfdestruct, selfdestruct)
986+
for (const addressToSelfdestructHex of selfdestruct) {
987+
this._result.selfdestruct.add(addressToSelfdestructHex)
988+
}
989+
if (this._common.isActivatedEIP(6780)) {
990+
// copy over the items to result via iterator
991+
for (const item of createdAddresses!) {
992+
this._result.createdAddresses!.add(item)
993+
}
994+
}
979995
// update stateRoot on current contract
980996
const account = await this._stateManager.getAccount(this._env.address)
981997
if (!account) {
@@ -1017,11 +1033,11 @@ export class Interpreter {
10171033

10181034
async _selfDestruct(toAddress: Address): Promise<void> {
10191035
// only add to refund if this is the first selfdestruct for the address
1020-
if (this._result.selfdestruct[bytesToHex(this._env.address.bytes)] === undefined) {
1036+
if (!this._result.selfdestruct.has(bytesToHex(this._env.address.bytes))) {
10211037
this.refundGas(this._common.param('gasPrices', 'selfdestructRefund'))
10221038
}
10231039

1024-
this._result.selfdestruct[bytesToHex(this._env.address.bytes)] = toAddress.bytes
1040+
this._result.selfdestruct.add(bytesToHex(this._env.address.bytes))
10251041

10261042
// Add to beneficiary balance
10271043
let toAccount = await this._stateManager.getAccount(toAddress)

packages/evm/src/message.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ interface MessageOpts {
2626
isCompiled?: boolean
2727
salt?: Uint8Array
2828
/**
29-
* A map of addresses to selfdestruct, see {@link Message.selfdestruct}
29+
* A set of addresses to selfdestruct, see {@link Message.selfdestruct}
3030
*/
31-
selfdestruct?: { [key: string]: boolean } | { [key: string]: Uint8Array }
31+
selfdestruct?: Set<string>
3232
/**
3333
* Map of addresses which were created (used in EIP 6780)
3434
*/
@@ -53,10 +53,9 @@ export class Message {
5353
salt?: Uint8Array
5454
containerCode?: Uint8Array /** container code for EOF1 contracts - used by CODECOPY/CODESIZE */
5555
/**
56-
* Map of addresses to selfdestruct. Key is the unprefixed address.
57-
* Value is a boolean when marked for destruction and replaced with a Uint8Array containing the address where the remaining funds are sent.
56+
* Set of addresses to selfdestruct. Key is the unprefixed address.
5857
*/
59-
selfdestruct?: { [key: string]: boolean } | { [key: string]: Uint8Array }
58+
selfdestruct?: Set<string>
6059
/**
6160
* Map of addresses which were created (used in EIP 6780)
6261
*/

packages/evm/src/types.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ export interface EVMRunCallOpts {
9292
*/
9393
salt?: Uint8Array
9494
/**
95-
* Addresses to selfdestruct. Defaults to none.
95+
* Addresses to selfdestruct. Defaults to the empty set.
9696
*/
97-
selfdestruct?: { [k: string]: boolean }
97+
selfdestruct?: Set<string>
9898
/**
9999
* Created addresses in current context. Used in EIP 6780
100100
*/
@@ -171,9 +171,9 @@ export interface EVMRunCodeOpts {
171171
*/
172172
isStatic?: boolean
173173
/**
174-
* Addresses to selfdestruct. Defaults to none.
174+
* Addresses to selfdestruct. Defaults to the empty set.
175175
*/
176-
selfdestruct?: { [k: string]: boolean }
176+
selfdestruct?: Set<string>
177177
/**
178178
* The address of the account that is executing this code (`address(this)`). Defaults to the zero address.
179179
*/

packages/vm/src/runTx.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -503,9 +503,8 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise<RunTxResult> {
503503
* Cleanup accounts
504504
*/
505505
if (results.execResult.selfdestruct !== undefined) {
506-
const keys = Object.keys(results.execResult.selfdestruct)
507-
for (const k of keys) {
508-
const address = new Address(hexToBytes(k))
506+
for (const addressToSelfdestructHex of results.execResult.selfdestruct) {
507+
const address = new Address(hexToBytes(addressToSelfdestructHex))
509508
if (this._common.isActivatedEIP(6780)) {
510509
// skip cleanup of addresses not in createdAddresses
511510
if (!results.execResult.createdAddresses!.has(address.toString())) {

packages/vm/test/tester/runners/BlockchainTestsRunner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ export async function runBlockchainTest(options: any, testData: any, t: tape.Tes
181181
await blockBuilder.revert() // will only revert if checkpointed
182182
}
183183

184-
const block = Block.fromRLPSerializedBlock(blockRlp, { common })
184+
const block = Block.fromRLPSerializedBlock(blockRlp, { common, setHardfork: TD })
185185
await blockchain.putBlock(block)
186186

187187
// This is a trick to avoid generating the canonical genesis

0 commit comments

Comments
 (0)