Skip to content

Commit 044f411

Browse files
[ETCM-912] Implement EXTCODESIZE changes
1 parent 1d62e13 commit 044f411

File tree

4 files changed

+86
-6
lines changed

4 files changed

+86
-6
lines changed

src/main/scala/io/iohk/ethereum/vm/OpCode.scala

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -452,13 +452,34 @@ case object CODECOPY extends OpCode(0x39, 3, 0, _.G_verylow) {
452452

453453
case object GASPRICE extends ConstOp(0x3a)(_.env.gasPrice)
454454

455-
case object EXTCODESIZE extends OpCode(0x3b, 1, 1, _.G_extcode) with ConstGas {
455+
case object EXTCODESIZE extends OpCode(0x3b, 1, 1, _.G_zero) {
456456
protected def exec[W <: WorldStateProxy[W, S], S <: Storage[S]](state: ProgramState[W, S]): ProgramState[W, S] = {
457-
val (addr, stack1) = state.stack.pop
458-
val codeSize = state.world.getCode(Address(addr)).size
457+
val (addrUint, stack1) = state.stack.pop
458+
val addr = Address(addrUint)
459+
val codeSize = state.world.getCode(addr).size
459460
val stack2 = stack1.push(UInt256(codeSize))
460-
state.withStack(stack2).step()
461+
state.withStack(stack2).addAccessedAddress(addr).step()
462+
}
463+
464+
protected def varGas[W <: WorldStateProxy[W, S], S <: Storage[S]](state: ProgramState[W, S]): BigInt = {
465+
466+
val currentBlockNumber = state.env.blockHeader.number
467+
val etcFork = state.config.blockchainConfig.etcForkForBlockNumber(currentBlockNumber)
468+
469+
val eip2929Enabled = isEip2929Enabled(etcFork)
470+
471+
if (eip2929Enabled) {
472+
val (addr, _) = state.stack.pop
473+
if (state.accessedAddresses.contains(Address(addr)))
474+
state.config.feeSchedule.G_warm_storage_read
475+
else
476+
state.config.feeSchedule.G_cold_account_access
477+
} else
478+
state.config.feeSchedule.G_extcode
461479
}
480+
481+
private def isEip2929Enabled(etcFork: EtcFork): Boolean = etcFork >= EtcForks.Magneto
482+
462483
}
463484

464485
case object EXTCODECOPY extends OpCode(0x3c, 4, 0, _.G_extcode) {

src/test/scala/io/iohk/ethereum/vm/CreateOpcodeSpec.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ class CreateOpcodeSpec extends AnyWordSpec with Matchers with ScalaCheckProperty
253253
result.world.getGuaranteedAccount(newAccountAddress())
254254
val addr = newAccountAddress()
255255

256-
result.stateOut.accessedAddresses should contain (addr)
256+
result.stateOut.accessedAddresses should contain(addr)
257257
}
258258
}
259259

src/test/scala/io/iohk/ethereum/vm/OpCodeGasSpec.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ class OpCodeGasSpec extends AnyFunSuite with OpCodeTesting with Matchers with Sc
5151
CALLVALUE -> G_base,
5252
CALLDATALOAD -> G_verylow,
5353
CALLDATASIZE -> G_base,
54-
EXTCODESIZE -> G_extcode,
5554
BLOCKHASH -> G_blockhash,
5655
COINBASE -> G_base,
5756
TIMESTAMP -> G_base,
@@ -582,5 +581,15 @@ class OpCodeGasSpec extends AnyFunSuite with OpCodeTesting with Matchers with Sc
582581

583582
}
584583

584+
test(EXTCODESIZE) { op =>
585+
val stateGen = getProgramStateGen(
586+
stackGen = getStackGen(elems = 1)
587+
)
588+
forAll(stateGen) { stateIn =>
589+
val stateOut = op.execute(stateIn)
590+
verifyGas(G_extcode, stateIn, stateOut)
591+
}
592+
}
593+
585594
verifyAllOpCodesRegistered(except = CREATE, CREATE2, CALL, CALLCODE, DELEGATECALL, STATICCALL, INVALID)
586595
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package io.iohk.ethereum.vm
2+
3+
import org.scalatest.funsuite.AnyFunSuite
4+
import org.scalatest.matchers.should.Matchers
5+
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
6+
7+
import io.iohk.ethereum.domain.Address
8+
import io.iohk.ethereum.vm.Generators._
9+
10+
import Fixtures.blockchainConfig
11+
12+
class OpCodeGasSpecPostEip2929 extends AnyFunSuite with OpCodeTesting with Matchers with ScalaCheckPropertyChecks {
13+
14+
override val config: EvmConfig = EvmConfig.MagnetoConfigBuilder(blockchainConfig)
15+
16+
import config.feeSchedule._
17+
18+
test(EXTCODESIZE) { op =>
19+
val stateGen = getProgramStateGen(
20+
evmConfig = config,
21+
stackGen = getStackGen(elems = 1),
22+
blockNumberGen = getUInt256Gen(Fixtures.MagnetoBlockNumber)
23+
)
24+
val codeGen = getByteStringGen(0, 512)
25+
26+
forAll(stateGen) { stateIn =>
27+
val (addrUint, _) = stateIn.stack.pop
28+
val addr = Address(addrUint)
29+
stateIn.accessedAddresses shouldNot contain(addr)
30+
31+
val stateOut = op.execute(stateIn)
32+
33+
verifyGas(G_cold_account_access, stateIn, stateOut)
34+
stateOut.accessedAddresses should contain(addr)
35+
}
36+
37+
forAll(stateGen, codeGen) { (stateIn, extCode) =>
38+
val (addrUint, _) = stateIn.stack.pop
39+
val addr = Address(addrUint)
40+
val program = Program(extCode)
41+
val world1 = stateIn.world.saveCode(addr, program.code)
42+
val stateInWithExtCode = stateIn.withWorld(world1).addAccessedAddress(addr)
43+
44+
val stateOut = op.execute(stateInWithExtCode)
45+
46+
verifyGas(G_warm_storage_read, stateIn, stateOut)
47+
stateOut.accessedAddresses should contain(addr)
48+
}
49+
}
50+
}

0 commit comments

Comments
 (0)