Skip to main content

fluentbase_types/
block_fuel.rs

1use crate::{SysFuncIdx, FUEL_DENOM_RATE, QUADRATIC_DIVISOR, QUADRATIC_WORD_FUEL_COST};
2use rwasm::{LinearFuelParams, QuadraticFuelParams, SyscallFuelParams};
3
4/// In this file, we define the fuel procedures that will be inserted by the rwasm translator
5/// before the builtin calls. Each fuel procedure is a set of rwasm Opcodes that will be
6/// executed. Fuel procedures can potentially access the variables of the function they are
7/// inserted into.
8/// Word is defined as 32 bytes, the same as in the EVM.
9macro_rules! no_fuel {
10    () => {
11        SyscallFuelParams::None
12    };
13}
14
15macro_rules! const_fuel {
16    ($base:expr) => {
17        SyscallFuelParams::Const($base as u64)
18    };
19}
20
21macro_rules! linear_fuel {
22    ($param_index:expr, $base:expr, $linear:expr) => {
23        SyscallFuelParams::LinearFuel(LinearFuelParams {
24            base_fuel: $base,
25            param_index: $param_index,
26            word_cost: $linear,
27        })
28    };
29}
30
31macro_rules! quadratic_fuel {
32    ($local_depth:expr, $word_cost:expr, $divisor:expr) => {
33        SyscallFuelParams::QuadraticFuel(QuadraticFuelParams {
34            divisor: $divisor,
35            local_depth: $local_depth,
36            word_cost: $word_cost,
37            fuel_denom_rate: FUEL_DENOM_RATE as u32,
38        })
39    };
40}
41
42// Common fuel cost constants
43pub const STATE_FUEL_COST: u32 = 20 * FUEL_DENOM_RATE as u32;
44pub const COPY_BASE_FUEL_COST: u32 = 20 * FUEL_DENOM_RATE as u32;
45pub const COPY_WORD_FUEL_COST: u32 = 3 * FUEL_DENOM_RATE as u32;
46pub const DEBUG_LOG_BASE_FUEL_COST: u32 = 50 * FUEL_DENOM_RATE as u32;
47pub const DEBUG_LOG_WORD_FUEL_COST: u32 = 16 * FUEL_DENOM_RATE as u32;
48pub const CHARGE_FUEL_BASE_COST: u32 = 20 * FUEL_DENOM_RATE as u32;
49pub const KECCAK_BASE_FUEL_COST: u32 = 30 * FUEL_DENOM_RATE as u32;
50pub const KECCAK_WORD_FUEL_COST: u32 = 6 * FUEL_DENOM_RATE as u32;
51pub const SHA256_BASE_FUEL_COST: u32 = 60 * FUEL_DENOM_RATE as u32;
52pub const SHA256_WORD_FUEL_COST: u32 = 12 * FUEL_DENOM_RATE as u32;
53pub const BLAKE3_BASE_FUEL_COST: u32 = 60 * FUEL_DENOM_RATE as u32;
54pub const BLAKE3_WORD_FUEL_COST: u32 = 12 * FUEL_DENOM_RATE as u32;
55
56// Ed25519
57pub const ED25519_DECOMPRESS_COST: u32 = 5_000 * FUEL_DENOM_RATE as u32;
58pub const ED25519_ADD_COST: u32 = 1_500 * FUEL_DENOM_RATE as u32;
59
60// Tower field (BN254/BLS12-381)
61pub const FP1_ADD_COST: u32 = 6 * FUEL_DENOM_RATE as u32;
62pub const FP1_MUL_COST: u32 = 24 * FUEL_DENOM_RATE as u32;
63pub const FP2_ADD_COST: u32 = 12 * FUEL_DENOM_RATE as u32;
64pub const FP2_MUL_COST: u32 = 48 * FUEL_DENOM_RATE as u32;
65pub const FP1_BLS_ADD_COST: u32 = 8 * FUEL_DENOM_RATE as u32;
66pub const FP1_BLS_MUL_COST: u32 = 32 * FUEL_DENOM_RATE as u32;
67pub const FP2_BLS_ADD_COST: u32 = 16 * FUEL_DENOM_RATE as u32;
68pub const FP2_BLS_MUL_COST: u32 = 64 * FUEL_DENOM_RATE as u32;
69
70// Secp256k1
71pub const SECP256K1_ADD_COST: u32 = 150 * FUEL_DENOM_RATE as u32;
72pub const SECP256K1_DOUBLE_COST: u32 = 150 * FUEL_DENOM_RATE as u32;
73pub const SECP256K1_DECOMPRESS_COST: u32 = 4_000 * FUEL_DENOM_RATE as u32;
74
75// Secp256r1
76pub const SECP256R1_ADD_COST: u32 = 150 * FUEL_DENOM_RATE as u32;
77pub const SECP256R1_DOUBLE_COST: u32 = 150 * FUEL_DENOM_RATE as u32;
78pub const SECP256R1_DECOMPRESS_COST: u32 = 4_000 * FUEL_DENOM_RATE as u32;
79
80// BN254
81pub const BN254_ADD_COST: u32 = 150 * FUEL_DENOM_RATE as u32;
82pub const BN254_DOUBLE_COST: u32 = 150 * FUEL_DENOM_RATE as u32;
83pub const BN254_MUL_COST: u32 = 6_000 * FUEL_DENOM_RATE as u32;
84pub const BN254_PAIRING_COST: u32 = 45_000 * FUEL_DENOM_RATE as u32;
85pub const BN254_G1_COMPRESS_COST: u32 = 600 * FUEL_DENOM_RATE as u32;
86pub const BN254_G1_DECOMPRESS_COST: u32 = 600 * FUEL_DENOM_RATE as u32;
87pub const BN254_G2_COMPRESS_COST: u32 = 1_200 * FUEL_DENOM_RATE as u32;
88pub const BN254_G2_DECOMPRESS_COST: u32 = 1_200 * FUEL_DENOM_RATE as u32;
89
90// BLS12-381
91pub const BLS_G1_ADD_COST: u32 = 600 * FUEL_DENOM_RATE as u32;
92pub const BLS_G2_ADD_COST: u32 = 4_500 * FUEL_DENOM_RATE as u32;
93pub const BLS_PAIRING_COST: u32 = 45_000 * FUEL_DENOM_RATE as u32;
94pub const BLS_MAP_G1_COST: u32 = 8_000 * FUEL_DENOM_RATE as u32;
95pub const BLS_MAP_G2_COST: u32 = 80_000 * FUEL_DENOM_RATE as u32;
96pub const BLS_G1_DOUBLE_COST: u32 = 600 * FUEL_DENOM_RATE as u32;
97pub const BLS_G1_DECOMPRESS_COST: u32 = 600 * FUEL_DENOM_RATE as u32;
98
99// Big integer
100pub const UINT256_MUL_MOD_COST: u32 = 8 * FUEL_DENOM_RATE as u32;
101pub const UINT256_X2048_MUL_COST: u32 = 5_000 * FUEL_DENOM_RATE as u32;
102
103/// Calldata surcharge threshold (128 KB).
104///
105/// Ethereum L1 rejects transactions above this size at the RPC level.
106/// Fluent L2 accepts large calldata but applies a quadratic surcharge above this threshold
107/// to bound block data to L1 blob capacity.
108pub const CALLDATA_QUADRATIC_THRESHOLD: u64 = 128 * 1024;
109
110/// Divisor in `surcharge = 3*words + words²/DIVISOR`.
111/// Chosen so that 14 × 128 KB exceeds 100M gas (max block gas):
112/// `DIVISOR < words²(53,248) / (100M - 7.4M linear) ≈ 30.6`
113pub const CALLDATA_QUADRATIC_DIVISOR: u64 = 30;
114
115/// Returns quadratic surcharge for `input_len` bytes above [`CALLDATA_QUADRATIC_THRESHOLD`].
116pub fn calldata_quadratic_surcharge(input_len: u64) -> u64 {
117    if input_len <= CALLDATA_QUADRATIC_THRESHOLD {
118        return 0;
119    }
120    let excess = input_len - CALLDATA_QUADRATIC_THRESHOLD;
121    let words = excess.div_ceil(32);
122    3 * words + words * words / CALLDATA_QUADRATIC_DIVISOR
123}
124
125pub(crate) fn calculate_syscall_fuel(sys_func_idx: SysFuncIdx) -> SyscallFuelParams {
126    use SysFuncIdx::*;
127    match sys_func_idx {
128        // input/output & state control (0x00)
129        EXIT => no_fuel!(),
130        STATE => const_fuel!(STATE_FUEL_COST),
131        READ_INPUT => linear_fuel!(1, COPY_BASE_FUEL_COST, COPY_WORD_FUEL_COST),
132        INPUT_SIZE => const_fuel!(STATE_FUEL_COST),
133        WRITE_OUTPUT => linear_fuel!(1, COPY_BASE_FUEL_COST, COPY_WORD_FUEL_COST),
134        OUTPUT_SIZE => const_fuel!(STATE_FUEL_COST),
135        READ_OUTPUT => linear_fuel!(1, COPY_BASE_FUEL_COST, COPY_WORD_FUEL_COST),
136        EXEC => quadratic_fuel!(3, QUADRATIC_WORD_FUEL_COST, QUADRATIC_DIVISOR),
137        RESUME => no_fuel!(),
138        FORWARD_OUTPUT => linear_fuel!(1, COPY_BASE_FUEL_COST, COPY_WORD_FUEL_COST),
139        CHARGE_FUEL_MANUALLY => no_fuel!(),
140        FUEL => const_fuel!(STATE_FUEL_COST),
141        DEBUG_LOG => linear_fuel!(1, DEBUG_LOG_BASE_FUEL_COST, DEBUG_LOG_WORD_FUEL_COST),
142        CHARGE_FUEL => const_fuel!(CHARGE_FUEL_BASE_COST),
143        ENTER_UNCONSTRAINED => no_fuel!(),
144        EXIT_UNCONSTRAINED => no_fuel!(),
145        // TODO: use correct fuel calculations here, once we implement `WRITE_FD`, no fuel for now
146        WRITE_FD => no_fuel!(),
147
148        // hashing functions (0x01)
149        KECCAK256 => linear_fuel!(2, KECCAK_BASE_FUEL_COST, KECCAK_WORD_FUEL_COST),
150        KECCAK256_PERMUTE => const_fuel!(KECCAK_BASE_FUEL_COST),
151        POSEIDON => linear_fuel!(2, 100, 20),
152        SHA256_EXTEND => const_fuel!(SHA256_BASE_FUEL_COST),
153        SHA256_COMPRESS => const_fuel!(SHA256_BASE_FUEL_COST),
154        SHA256 => linear_fuel!(2, SHA256_BASE_FUEL_COST, SHA256_WORD_FUEL_COST),
155        BLAKE3 => linear_fuel!(2, BLAKE3_BASE_FUEL_COST, BLAKE3_WORD_FUEL_COST),
156
157        // ed25519 (0x02)
158        ED25519_DECOMPRESS => const_fuel!(ED25519_DECOMPRESS_COST),
159        ED25519_ADD => const_fuel!(ED25519_ADD_COST),
160
161        // fp1/fp2 tower field (0x03)
162        TOWER_FP1_BN254_ADD | TOWER_FP1_BN254_SUB => const_fuel!(FP1_ADD_COST),
163        TOWER_FP1_BN254_MUL => const_fuel!(FP1_MUL_COST),
164        TOWER_FP1_BLS12381_ADD | TOWER_FP1_BLS12381_SUB => const_fuel!(FP1_BLS_ADD_COST),
165        TOWER_FP1_BLS12381_MUL => const_fuel!(FP1_BLS_MUL_COST),
166        TOWER_FP2_BN254_ADD | TOWER_FP2_BN254_SUB => const_fuel!(FP2_ADD_COST),
167        TOWER_FP2_BN254_MUL => const_fuel!(FP2_MUL_COST),
168        TOWER_FP2_BLS12381_ADD | TOWER_FP2_BLS12381_SUB => const_fuel!(FP2_BLS_ADD_COST),
169        TOWER_FP2_BLS12381_MUL => const_fuel!(FP2_BLS_MUL_COST),
170
171        // secp256k1 (0x04)
172        SECP256K1_ADD => const_fuel!(SECP256K1_ADD_COST),
173        SECP256K1_DECOMPRESS => const_fuel!(SECP256K1_DECOMPRESS_COST),
174        SECP256K1_DOUBLE => const_fuel!(SECP256K1_DOUBLE_COST),
175        // secp256r1 (0x05)
176        SECP256R1_ADD => const_fuel!(SECP256R1_ADD_COST),
177        SECP256R1_DECOMPRESS => const_fuel!(SECP256R1_DECOMPRESS_COST),
178        SECP256R1_DOUBLE => const_fuel!(SECP256R1_DOUBLE_COST),
179
180        // bls12381 (0x06)
181        BLS12381_ADD => const_fuel!(BLS_G1_ADD_COST),
182        BLS12381_DECOMPRESS => const_fuel!(BLS_G1_DECOMPRESS_COST),
183        BLS12381_DOUBLE => const_fuel!(BLS_G1_DOUBLE_COST),
184
185        // bn254 (0x07)
186        BN254_ADD => const_fuel!(BN254_ADD_COST),
187        BN254_DOUBLE => const_fuel!(BN254_DOUBLE_COST),
188
189        // uint256 (0x08)
190        UINT256_MUL_MOD => const_fuel!(UINT256_MUL_MOD_COST),
191        UINT256_X2048_MUL => const_fuel!(UINT256_X2048_MUL_COST),
192    }
193}