Modular exponentiation precompile — address 0x05 (EIP-198).
Computes base^exp mod modulus over arbitrarily large integers.
Gas schedule (EIP-198, Byzantium through Istanbul)
gas = floor(multiplication_complexity * iteration_count / 20)
where multiplication_complexity of x = max(base_length, mod_length) is
x^2 for x <= 64, x^2 / 4 + 96x - 3072 for x <= 1024, and
x^2 / 16 + 480x - 199680 above, and iteration_count is computed as for
EIP-2565 below.
Gas schedule (EIP-2565, Berlin through Prague)
gas = max(200, floor(multiplication_complexity * iteration_count / 3))
where:
multiplication_complexity = ceil(max(base_length, mod_length) / 8)^2(equivalently((max(base_length, mod_length) + 7) div 8)^2in integer arithmetic).iteration_countis derived from the exponent length and the top bits of the exponent:- if
exp_length <= 32:0when exponent is zero, otherwise the 0-indexed highest set bit of the exponent. - if
exp_length > 32:8 * (exp_length - 32) + highest_bit_index(exp[0..31])where the highest bit index of an all-zero 32-byte prefix is treated as 0. - the result is floored at
1.
- if
Gas schedule (EIP-7883, Osaka onward)
gas = max(500, multiplication_complexity * iteration_count)
where:
multiplication_complexityis16whenmax(base_length, mod_length) <= 32, otherwise2 * ceil(max(base_length, mod_length) / 8)^2.iteration_countis computed as above, except the per-byte multiplier for exponents longer than 32 bytes is16instead of8.
Input bounds (EIP-7823, Osaka onward)
If base_length, exp_length, or mod_length exceeds 1024 bytes, the call
fails with {:error, :invalid_input}, consuming all gas it was given.
execute/3 picks the gas schedule and bounds from the hardfork it is given.
Gas is charged from the 96-byte header and at most the first 32 exponent bytes before any operand is read, so oversized declared lengths fail with out-of-gas instead of allocating.
Input format
- bytes
0..31:base_length(big-endian uint256) - bytes
32..63:exp_length(big-endian uint256) - bytes
64..95:mod_length(big-endian uint256) - bytes
96..: concatenatedbase || exponent || modulus
If the input is shorter than required by those lengths, missing bytes are treated as zero (right-padding behavior).
Output is the big-endian value of base^exp mod modulus, left-padded with
zeros to exactly mod_length bytes. If modulus == 0 or mod_length == 0,
the precompile returns mod_length zero bytes.
Summary
Functions
Executes the ModExp precompile with the gas schedule and input bounds of
hardfork (default: Cancun).
Functions
@spec execute(binary(), non_neg_integer(), EEVM.HardforkConfig.t()) :: {:ok, binary(), non_neg_integer()} | {:error, :out_of_gas | :invalid_input}
Executes the ModExp precompile with the gas schedule and input bounds of
hardfork (default: Cancun).