Skip to content

Commit 9bcbb6e

Browse files
[ETCM-921] Implement gas calculation changes in *CALL codes
1 parent 09b187d commit 9bcbb6e

File tree

3 files changed

+826
-18
lines changed

3 files changed

+826
-18
lines changed

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

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,24 @@ object OpCode {
164164
val end = (offset + size).min(bytes.size).toInt
165165
bytes.slice(start, end).padToByteString(size.toInt, 0.toByte)
166166
}
167+
168+
def addressAccessCost[W <: WorldStateProxy[W, S], S <: Storage[S]](state: ProgramState[W, S], address: Address)(
169+
preGasFn: FeeSchedule => BigInt,
170+
postColdGasFn: FeeSchedule => BigInt,
171+
postWarmGasFn: FeeSchedule => BigInt
172+
): BigInt = {
173+
val currentBlockNumber = state.env.blockHeader.number
174+
val etcFork = state.config.blockchainConfig.etcForkForBlockNumber(currentBlockNumber)
175+
val eip2929Enabled = isEip2929Enabled(etcFork)
176+
if (eip2929Enabled) {
177+
val addr = address
178+
if (state.accessedAddresses.contains(addr))
179+
postWarmGasFn(state.config.feeSchedule)
180+
else
181+
postColdGasFn(state.config.feeSchedule)
182+
} else
183+
preGasFn(state.config.feeSchedule)
184+
}
167185
}
168186

169187
/** Base class for all the opcodes of the EVM
@@ -213,22 +231,10 @@ trait AddrAccessGas { self: OpCode =>
213231
private def coldGasFn: FeeSchedule => BigInt = _.G_cold_account_access
214232
private def warmGasFn: FeeSchedule => BigInt = _.G_warm_storage_read
215233

216-
override protected def baseGas[W <: WorldStateProxy[W, S], S <: Storage[S]](state: ProgramState[W, S]): BigInt = {
217-
val currentBlockNumber = state.env.blockHeader.number
218-
val etcFork = state.config.blockchainConfig.etcForkForBlockNumber(currentBlockNumber)
219-
val eip2929Enabled = isEip2929Enabled(etcFork)
220-
if (eip2929Enabled) {
221-
val addr = address(state)
222-
if (state.accessedAddresses.contains(addr))
223-
warmGasFn(state.config.feeSchedule)
224-
else
225-
coldGasFn(state.config.feeSchedule)
226-
} else
227-
baseGasFn(state.config.feeSchedule)
228-
}
234+
override protected def baseGas[W <: WorldStateProxy[W, S], S <: Storage[S]](state: ProgramState[W, S]): BigInt =
235+
OpCode.addressAccessCost(state, address(state))(baseGasFn, coldGasFn, warmGasFn)
229236

230237
protected def address[W <: WorldStateProxy[W, S], S <: Storage[S]](state: ProgramState[W, S]): Address
231-
232238
}
233239

234240
sealed trait ConstGas { self: OpCode =>
@@ -1065,6 +1071,7 @@ abstract class CallOp(code: Int, delta: Int, alpha: Int) extends OpCode(code, de
10651071
.withInternalTxs(internalTx +: result.internalTxs)
10661072
.withLogs(result.logs)
10671073
.withReturnData(result.returnData)
1074+
.addAccessedAddress(toAddr)
10681075
.step()
10691076
}
10701077
}
@@ -1159,7 +1166,9 @@ abstract class CallOp(code: Int, delta: Int, alpha: Int) extends OpCode(code, de
11591166
else 0
11601167

11611168
val c_xfer: BigInt = if (endowment.isZero) 0 else state.config.feeSchedule.G_callvalue
1162-
state.config.feeSchedule.G_call + c_xfer + c_new
1169+
1170+
val callCost: BigInt = OpCode.addressAccessCost(state, to)(_.G_call, _.G_cold_account_access, _.G_warm_storage_read)
1171+
callCost + c_xfer + c_new
11631172
}
11641173
}
11651174

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class CallOpFixture(val config: EvmConfig, val startState: MockWorldState) {
163163

164164
val fakeHeader: BlockHeader = BlockFixtures.ValidBlock.header.copy(number = 0, unixTimestamp = 0)
165165

166-
val context: PC = ProgramContext(
166+
lazy val context: PC = ProgramContext(
167167
callerAddr = callerAddr,
168168
originAddr = callerAddr,
169169
recipientAddr = Some(ownerAddr),
@@ -191,7 +191,8 @@ class CallOpFixture(val config: EvmConfig, val startState: MockWorldState) {
191191
inOffset: UInt256 = UInt256.Zero,
192192
inSize: UInt256 = inputData.size,
193193
outOffset: UInt256 = inputData.size,
194-
outSize: UInt256 = inputData.size / 2
194+
outSize: UInt256 = inputData.size / 2,
195+
toAccessed: Boolean = false
195196
) {
196197

197198
val vm = new TestVM
@@ -205,7 +206,8 @@ class CallOpFixture(val config: EvmConfig, val startState: MockWorldState) {
205206
private val stack = Stack.empty().push(if (op == DELEGATECALL) paramsForDelegate else params)
206207
private val mem = Memory.empty.store(UInt256.Zero, inputData)
207208

208-
val stateIn: PS = ProgramState(vm, context, env).withStack(stack).withMemory(mem)
209+
val baseStateIn: PS = ProgramState(vm, context, env).withStack(stack).withMemory(mem)
210+
val stateIn: PS = if (toAccessed) baseStateIn.addAccessedAddress(to) else baseStateIn
209211
val stateOut: PS = op.execute(stateIn)
210212
val world: MockWorldState = stateOut.world
211213

0 commit comments

Comments
 (0)