Background
The Cadence Arch precompile's gas costs are hardcoded in fvm/evm/precompiles/arch.go:39-52 (FlowBlockHeightFixedGas, ProofVerifierBaseGas, ProofVerifierGasMultiplerPerSignature, RandomSourceGas, RevertibleRandomGas). Changing any of them requires a flow-go release, which leaves no operational lever for retuning as the Cadence runtime's underlying costs evolve.
Proposal
Make the costs calibratable through the existing ExecutionEffortWeights mechanism by adding new ComputationKinds whose weight is interpreted as EVM gas per intensity rather than FVM-computation units. The precompile reads the weight inside ComputeGas; the cost still flows into the FVM via the existing meterGasUsage(res) call (fvm/evm/handler/handler.go:714-720).
New kinds (in fvm/environment/meter.go):
ComputationKindEVMArchFlowBlockHeight
ComputationKindEVMArchVerifyCOAOwnershipBase
ComputationKindEVMArchVerifyCOAOwnershipPerSig
ComputationKindEVMArchGetRandomSource
ComputationKindEVMArchRevertibleRandom
A banner comment documents the EVM-gas-vs-FVM-units distinction; the EVMArch* prefix flags them as a separate semantic class.
Default weights are added to MainnetExecutionEffortWeights matching today's constants (shifted by MeterExecutionInternalPrecisionBytes).
A new accessor on backends.Backend:
ComputationWeight(kind common.ComputationKind) (uint64, bool)
reads from the per-tx weights map populated by ExecutionParametersComputer.Compute (fvm/executionParameters.go:121). precompiles.ArchContract takes a closure that does the lookup, applies the precision shift, and falls back to the hardcoded constant if absent or zero. Lookups happen per-call (the handler is bound to a runtime that outlives transactions via RegisterOnSwapCallback at fvm/runtime/cadence_function_declarations.go:113).
Intensity tracking
Calibration needs per-kind invocation data. Because the precompile bypasses MeterComputation, and ExecutionState.MeterComputation is suppressed when meteringEnabled is false (fvm/storage/state/execution_state.go:224-228), the new kinds won't appear in ComputationIntensities through the existing path.
A new method is added to the meter / execution state / backend:
RecordIntensity(kind common.ComputationKind, intensity uint64)
It records the intensity unconditionally (bypassing the meteringEnabled guard) and never touches computationUsed. Each precompile's Run calls it after the work completes — proof verifier with the per-signature count, the others with intensity 1. The resulting intensities feed the existing weight-tuning pipeline.
Backward compatibility
Missing weights fall back to the current hardcoded constants, so default behavior is unchanged. On-network migration is optional via a service-account transaction following SetExecutionEffortWeightsTransaction (fvm/blueprints/fees.go:172). EVM transaction semantics don't change unless the in-state weights are explicitly updated.
Background
The Cadence Arch precompile's gas costs are hardcoded in
fvm/evm/precompiles/arch.go:39-52(FlowBlockHeightFixedGas,ProofVerifierBaseGas,ProofVerifierGasMultiplerPerSignature,RandomSourceGas,RevertibleRandomGas). Changing any of them requires a flow-go release, which leaves no operational lever for retuning as the Cadence runtime's underlying costs evolve.Proposal
Make the costs calibratable through the existing
ExecutionEffortWeightsmechanism by adding newComputationKinds whose weight is interpreted as EVM gas per intensity rather than FVM-computation units. The precompile reads the weight insideComputeGas; the cost still flows into the FVM via the existingmeterGasUsage(res)call (fvm/evm/handler/handler.go:714-720).New kinds (in
fvm/environment/meter.go):ComputationKindEVMArchFlowBlockHeightComputationKindEVMArchVerifyCOAOwnershipBaseComputationKindEVMArchVerifyCOAOwnershipPerSigComputationKindEVMArchGetRandomSourceComputationKindEVMArchRevertibleRandomA banner comment documents the EVM-gas-vs-FVM-units distinction; the
EVMArch*prefix flags them as a separate semantic class.Default weights are added to
MainnetExecutionEffortWeightsmatching today's constants (shifted byMeterExecutionInternalPrecisionBytes).A new accessor on
backends.Backend:reads from the per-tx weights map populated by
ExecutionParametersComputer.Compute(fvm/executionParameters.go:121).precompiles.ArchContracttakes a closure that does the lookup, applies the precision shift, and falls back to the hardcoded constant if absent or zero. Lookups happen per-call (the handler is bound to a runtime that outlives transactions viaRegisterOnSwapCallbackatfvm/runtime/cadence_function_declarations.go:113).Intensity tracking
Calibration needs per-kind invocation data. Because the precompile bypasses
MeterComputation, andExecutionState.MeterComputationis suppressed whenmeteringEnabledis false (fvm/storage/state/execution_state.go:224-228), the new kinds won't appear inComputationIntensitiesthrough the existing path.A new method is added to the meter / execution state / backend:
It records the intensity unconditionally (bypassing the
meteringEnabledguard) and never touchescomputationUsed. Each precompile'sRuncalls it after the work completes — proof verifier with the per-signature count, the others with intensity 1. The resulting intensities feed the existing weight-tuning pipeline.Backward compatibility
Missing weights fall back to the current hardcoded constants, so default behavior is unchanged. On-network migration is optional via a service-account transaction following
SetExecutionEffortWeightsTransaction(fvm/blueprints/fees.go:172). EVM transaction semantics don't change unless the in-state weights are explicitly updated.