diff --git a/tezt/lib_ethereum/configuration.ml b/tezt/lib_ethereum/configuration.ml index 182b53a899fff45ef13be4d3fa80d25e43368211..d05e1a3690ca8ca1fec9e2a36604448fa7b78dff 100644 --- a/tezt/lib_ethereum/configuration.ml +++ b/tezt/lib_ethereum/configuration.ml @@ -2,13 +2,14 @@ (* *) (* SPDX-License-Identifier: MIT *) (* Copyright (c) 2023 Nomadic Labs *) +(* Copyright (c) 2024 Trilitech *) (* *) (*****************************************************************************) let default_bootstrap_account_balance = Wei.of_eth_int 9999 let make_config ?bootstrap_accounts ?ticketer ?administrator ?sequencer - ?delayed_bridge () = + ?delayed_bridge ?(base_fee = Wei.zero) () = let open Sc_rollup_helpers.Installer_kernel_config in let ticketer = Option.fold @@ -60,8 +61,14 @@ let make_config ?bootstrap_accounts ?ticketer ?administrator ?sequencer ~none:[] delayed_bridge in + let base_fee = + let to_ = Durable_storage_path.base_fee_path in + let value = Wei.(to_le_bytes base_fee) |> Hex.of_bytes |> Hex.show in + [Set {value; to_}] + in match ticketer @ bootstrap_accounts @ administrator @ sequencer @ delayed_bridge + @ base_fee with | [] -> None | res -> Some (`Config res) diff --git a/tezt/lib_ethereum/configuration.mli b/tezt/lib_ethereum/configuration.mli index f553e0da20b66219d764c16bb95cac3f17f3fac6..85454bd5f11ce9959ed2cc03747f426bb264b7a5 100644 --- a/tezt/lib_ethereum/configuration.mli +++ b/tezt/lib_ethereum/configuration.mli @@ -2,6 +2,7 @@ (* *) (* SPDX-License-Identifier: MIT *) (* Copyright (c) 2023 Nomadic Labs *) +(* Copyright (c) 2024 Trilitech *) (* *) (*****************************************************************************) @@ -17,5 +18,6 @@ val make_config : ?administrator:string -> ?sequencer:string -> ?delayed_bridge:string -> + ?base_fee:Wei.t -> unit -> [> `Config of Sc_rollup_helpers.Installer_kernel_config.instr list] option diff --git a/tezt/lib_ethereum/durable_storage_path.ml b/tezt/lib_ethereum/durable_storage_path.ml index cfb87a6f0ed0c2c4b98ed811a244592a6400eb55..28696a0b2263ee795abe29b6335ad1ce6ba3aeb9 100644 --- a/tezt/lib_ethereum/durable_storage_path.ml +++ b/tezt/lib_ethereum/durable_storage_path.ml @@ -3,6 +3,7 @@ (* Open Source License *) (* Copyright (c) 2023 Nomadic Labs *) (* Copyright (c) 2023 Functori *) +(* Copyright (c) 2024 Trilitech *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -53,3 +54,5 @@ let sequencer = evm "/sequencer" let kernel_boot_wasm = kernel "/boot.wasm" let delayed_bridge_path = evm "/delayed_bridge" + +let base_fee_path = evm "/base_fee" diff --git a/tezt/lib_ethereum/durable_storage_path.mli b/tezt/lib_ethereum/durable_storage_path.mli index 41217ce74586a37fba3a25661882e56c10ab22bc..f61f91e86ab05f5252456fe6508b9ff565e1473c 100644 --- a/tezt/lib_ethereum/durable_storage_path.mli +++ b/tezt/lib_ethereum/durable_storage_path.mli @@ -3,6 +3,7 @@ (* Open Source License *) (* Copyright (c) 2023 Nomadic Labs *) (* Copyright (c) 2023 Functori *) +(* Copyright (c) 2024 Trilitech *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -58,3 +59,6 @@ val kernel_boot_wasm : path (** [delayed_bridge_path] is the path to the delayed transaction bridge contract. *) val delayed_bridge_path : path + +(** [base_fee_path] is the path to the base fee, charged on every transaction. *) +val base_fee_path : path diff --git a/tezt/lib_ethereum/wei.ml b/tezt/lib_ethereum/wei.ml index 9b86a59d79529bd682d2a50844af6bb95f6767f6..db29854199f2f3d6885d6dc889312da8808c8f76 100644 --- a/tezt/lib_ethereum/wei.ml +++ b/tezt/lib_ethereum/wei.ml @@ -66,6 +66,8 @@ let ( * ) = Z.mul let ( / ) = Z.div +let cdiv = Z.cdiv + let typ = Check.comparable (fun fmt t -> Format.fprintf fmt "%s" (to_string t)) diff --git a/tezt/lib_ethereum/wei.mli b/tezt/lib_ethereum/wei.mli index 1e9b41829d4329bac569cb9423705ff78b4f9f91..a89e66133cb6732048cf949550b2ea32abfe5c68 100644 --- a/tezt/lib_ethereum/wei.mli +++ b/tezt/lib_ethereum/wei.mli @@ -80,6 +80,9 @@ val ( * ) : t -> Z.t -> t (** Division. This doesn't perform any bound checks. *) val ( / ) : t -> Z.t -> t +(** Division, rounding towards +oo. *) +val cdiv : t -> Z.t -> t + (** The wei {!Check.typ}. *) val typ : t Check.typ diff --git a/tezt/tests/evm_rollup.ml b/tezt/tests/evm_rollup.ml index 09290d64933062f87d5cdc68005cd79ec96d636e..2a15aaa1a0da5e4dfba7a46b6fa1b03a359bad43 100644 --- a/tezt/tests/evm_rollup.ml +++ b/tezt/tests/evm_rollup.ml @@ -81,6 +81,22 @@ let check_tx_failed ~endpoint ~tx = Check.(is_false status) ~error_msg:"Expected transaction to fail." ; unit +(* Check simple transfer base fee is correct + + We apply a flat base fee to every tx - which is paid through an + increase in estimate gas used at the given price. +*) +let check_tx_gas_for_base_fee ~base_fee ~gas_price ~gas_used = + let expected_gas_used = 21000l in + let gas_for_base_fee = Z.of_int32 (Int32.sub gas_used expected_gas_used) in + let gas_price = gas_price |> Z.of_int32 in + (* integer division truncates - so we make sure to take ceil(a/b) not floor(a/b). + otherwise we'd end up with very slightly less gas than needed to cover the + base fee. *) + let actual_gas_for_base_fee = Wei.cdiv base_fee gas_price in + Check.((actual_gas_for_base_fee = Wei.to_wei_z gas_for_base_fee) Wei.typ) + ~error_msg:"Unexpected base fee" + let check_status_n_logs ~endpoint ~status ~logs ~tx = let* receipt = Eth_cli.get_receipt ~endpoint ~tx in match receipt with @@ -267,8 +283,9 @@ let setup_evm_kernel ?config ?(kernel_installee = Constant.WASM.evm_kernel) ?(originator_key = Constant.bootstrap1.public_key_hash) ?(rollup_operator_key = Constant.bootstrap1.public_key_hash) ?(bootstrap_accounts = Eth_account.bootstrap_accounts) - ?(with_administrator = true) ~admin ?commitment_period ?challenge_window - ?timestamp ?(setup_mode = Setup_proxy {devmode = true}) protocol = + ?(with_administrator = true) ?base_fee ~admin ?commitment_period + ?challenge_window ?timestamp ?(setup_mode = Setup_proxy {devmode = true}) + protocol = let* node, client = setup_l1 ?commitment_period ?challenge_window ?timestamp protocol in @@ -294,6 +311,7 @@ let setup_evm_kernel ?config ?(kernel_installee = Constant.WASM.evm_kernel) in Configuration.make_config ~bootstrap_accounts + ?base_fee ?ticketer ?administrator ?sequencer @@ -377,7 +395,7 @@ let setup_evm_kernel ?config ?(kernel_installee = Constant.WASM.evm_kernel) } let register_test ?config ~title ~tags ?(admin = None) ?uses ?commitment_period - ?challenge_window ?bootstrap_accounts ~setup_mode f = + ?challenge_window ?bootstrap_accounts ?base_fee ~setup_mode f = let extra_tag = match setup_mode with | Setup_proxy _ -> "proxy" @@ -406,6 +424,7 @@ let register_test ?config ~title ~tags ?(admin = None) ?uses ?commitment_period ?commitment_period ?challenge_window ?bootstrap_accounts + ?base_fee ~admin ~setup_mode protocol @@ -428,7 +447,7 @@ let register_proxy ?config ~title ~tags ?uses ?admin ?commitment_period ~setup_mode:(Setup_proxy {devmode = true}) let register_both ~title ~tags ?uses ?admin ?commitment_period ?challenge_window - ?bootstrap_accounts ?config ?time_between_blocks f protocols = + ?bootstrap_accounts ?base_fee ?config ?time_between_blocks f protocols = let register = register_test ?config @@ -439,6 +458,7 @@ let register_both ~title ~tags ?uses ?admin ?commitment_period ?challenge_window ?commitment_period ?challenge_window ?bootstrap_accounts + ?base_fee f protocols in @@ -1364,7 +1384,7 @@ let make_transfer ?data ~value ~sender ~receiver full_evm_setup = receiver_balance_after; } -let transfer ?data ~evm_setup () = +let transfer ?data ~base_fee ~evm_setup () = let sender, receiver = (Eth_account.bootstrap_accounts.(0), Eth_account.bootstrap_accounts.(1)) in @@ -1389,12 +1409,13 @@ let transfer ?data ~evm_setup () = let* receipt = Eth_cli.get_receipt ~endpoint:evm_setup.endpoint ~tx:tx_object.hash in - let fees = + let gas_used, gas_price = match receipt with | Some Transaction.{status = true; gasUsed; effectiveGasPrice; _} -> - expected_gas_fees ~gas_price:effectiveGasPrice ~gas_used:gasUsed + (gasUsed, effectiveGasPrice) | _ -> Test.fail "Transaction didn't succeed" in + let fees = expected_gas_fees ~gas_price ~gas_used in Check.( Wei.(sender_balance_after = sender_balance_before - value - fees) Wei.typ) ~error_msg: @@ -1413,17 +1434,21 @@ let transfer ?data ~evm_setup () = ~error_msg:"Unexpected transaction's receiver" ; Check.((tx_object.value = value) Wei.typ) ~error_msg:"Unexpected transaction's value" ; + if Option.is_none data then + check_tx_gas_for_base_fee ~base_fee ~gas_used ~gas_price ; unit let test_l2_transfer = - let test_f ~protocol:_ ~evm_setup = transfer ~evm_setup () in + let base_fee = Wei.zero in + let test_f ~protocol:_ ~evm_setup = transfer ~evm_setup ~base_fee () in let title = "Check L2 transfers are applied" in let tags = ["evm"; "l2_transfer"] in register_both ~title ~tags test_f let test_chunked_transaction = + let base_fee = Wei.zero in let test_f ~protocol:_ ~evm_setup = - transfer ~data:("0x" ^ String.make 12_000 'a') ~evm_setup () + transfer ~data:("0x" ^ String.make 12_000 'a') ~base_fee ~evm_setup () in let title = "Check L2 chunked transfers are applied" in let tags = ["evm"; "l2_transfer"; "chunked"] in