Skip to content

Commit

Permalink
ref: rework gas usage reporting (#203)
Browse files Browse the repository at this point in the history
Partially completes #170
  • Loading branch information
alexfertel authored Jul 18, 2024
1 parent bc4abc3 commit a2cb3c6
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 252 deletions.
68 changes: 14 additions & 54 deletions benches/src/access_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use alloy::{
primitives::Address,
providers::ProviderBuilder,
sol,
sol_types::SolConstructor,
sol_types::{SolCall, SolConstructor},
};
use e2e::{receipt, Account};

use crate::ArbOtherFields;
use crate::report::Report;

sol!(
#[sol(rpc)]
Expand All @@ -33,7 +33,7 @@ const ROLE: [u8; 32] =
const NEW_ADMIN_ROLE: [u8; 32] =
hex!("879ce0d4bfd332649ca3552efe772a38d64a315eb70ab69689fd309c735946b5");

pub async fn bench() -> eyre::Result<()> {
pub async fn bench() -> eyre::Result<Report> {
let alice = Account::new().await?;
let alice_addr = alice.address();
let alice_wallet = ProviderBuilder::new()
Expand All @@ -55,61 +55,21 @@ pub async fn bench() -> eyre::Result<()> {
let contract_bob = AccessControl::new(contract_addr, &bob_wallet);

// IMPORTANT: Order matters!
use AccessControl::*;
#[rustfmt::skip]
let receipts = vec![
("hasRole(DEFAULT_ADMIN_ROLE, alice)", receipt!(contract.hasRole(DEFAULT_ADMIN_ROLE.into(), alice_addr))?),
("getRoleAdmin(ROLE)", receipt!(contract.getRoleAdmin(ROLE.into()))?),
("revokeRole(ROLE, alice)", receipt!(contract.revokeRole(ROLE.into(), alice_addr))?),
("grantRole(ROLE, bob)", receipt!(contract.grantRole(ROLE.into(), bob_addr))?),
("renounceRole(ROLE, bob)", receipt!(contract_bob.renounceRole(ROLE.into(), bob_addr))?),
("setRoleAdmin(ROLE, NEW_ADMIN_ROLE)", receipt!(contract.setRoleAdmin(ROLE.into(), NEW_ADMIN_ROLE.into()))?),
(hasRoleCall::SIGNATURE, receipt!(contract.hasRole(DEFAULT_ADMIN_ROLE.into(), alice_addr))?),
(getRoleAdminCall::SIGNATURE, receipt!(contract.getRoleAdmin(ROLE.into()))?),
(revokeRoleCall::SIGNATURE, receipt!(contract.revokeRole(ROLE.into(), alice_addr))?),
(grantRoleCall::SIGNATURE, receipt!(contract.grantRole(ROLE.into(), bob_addr))?),
(renounceRoleCall::SIGNATURE, receipt!(contract_bob.renounceRole(ROLE.into(), bob_addr))?),
(setRoleAdminCall::SIGNATURE, receipt!(contract.setRoleAdmin(ROLE.into(), NEW_ADMIN_ROLE.into()))?),
];

// Calculate the width of the longest function name.
let max_name_width = receipts
.iter()
.max_by_key(|x| x.0.len())
.expect("should at least bench one function")
.0
.len();
let name_width = max_name_width.max("AccessControl".len());

// Calculate the total width of the table.
let total_width = name_width + 3 + 6 + 3 + 6 + 3 + 20 + 4; // 3 for padding, 4 for outer borders

// Print the table header.
println!("+{}+", "-".repeat(total_width - 2));
println!(
"| {:<width$} | L2 Gas | L1 Gas | Effective Gas |",
"AccessControl",
width = name_width
);
println!(
"|{}+--------+--------+----------------------|",
"-".repeat(name_width + 2)
);

// Print each row.
for (func_name, receipt) in receipts {
let l2_gas = receipt.gas_used;
let arb_fields: ArbOtherFields = receipt.other.deserialize_into()?;
let l1_gas = arb_fields.gas_used_for_l1.to::<u128>();
let effective_gas = l2_gas - l1_gas;

println!(
"| {:<width$} | {:>6} | {:>6} | {:>20} |",
func_name,
l2_gas,
l1_gas,
effective_gas,
width = name_width
);
}

// Print the table footer.
println!("+{}+", "-".repeat(total_width - 2));

Ok(())
let report = receipts
.into_iter()
.try_fold(Report::new("AccessControl"), Report::add)?;
Ok(report)
}

async fn deploy(account: &Account) -> Address {
Expand Down
81 changes: 20 additions & 61 deletions benches/src/erc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ use alloy::{
primitives::Address,
providers::ProviderBuilder,
sol,
sol_types::SolConstructor,
sol_types::{SolCall, SolConstructor},
uint,
};
use alloy_primitives::U256;
use e2e::{receipt, Account};

use crate::ArbOtherFields;
use crate::report::Report;

sol!(
#[sol(rpc)]
Expand Down Expand Up @@ -39,7 +39,7 @@ const TOKEN_NAME: &str = "Test Token";
const TOKEN_SYMBOL: &str = "TTK";
const CAP: U256 = uint!(1_000_000_U256);

pub async fn bench() -> eyre::Result<()> {
pub async fn bench() -> eyre::Result<Report> {
let alice = Account::new().await?;
let alice_addr = alice.address();
let alice_wallet = ProviderBuilder::new()
Expand All @@ -61,68 +61,27 @@ pub async fn bench() -> eyre::Result<()> {
let contract_bob = Erc20::new(contract_addr, &bob_wallet);

// IMPORTANT: Order matters!
use Erc20::*;
#[rustfmt::skip]
let receipts = vec![
("name()", receipt!(contract.name())?),
("symbol()", receipt!(contract.symbol())?),
("decimals()", receipt!(contract.decimals())?),
("totalSupply()", receipt!(contract.totalSupply())?),
("balanceOf(alice)", receipt!(contract.balanceOf(alice_addr))?),
("allowance(alice, bob)", receipt!(contract.allowance(alice_addr, bob_addr))?),
("cap()", receipt!(contract.cap())?),
("mint(alice, 10)", receipt!(contract.mint(alice_addr, uint!(10_U256)))?),
("burn(1)", receipt!(contract.burn(uint!(1_U256)))?),
("transfer(bob, 1)", receipt!(contract.transfer(bob_addr, uint!(1_U256)))?),
("approve(bob, 5)", receipt!(contract.approve(bob_addr, uint!(5_U256)))?),
("burnFrom(alice, 1)", receipt!(contract_bob.burnFrom(alice_addr, uint!(1_U256)))?),
("transferFrom(alice, bob, 5)", receipt!(contract_bob.transferFrom(alice_addr, bob_addr, uint!(4_U256)))?),
(nameCall::SIGNATURE, receipt!(contract.name())?),
(symbolCall::SIGNATURE, receipt!(contract.symbol())?),
(decimalsCall::SIGNATURE, receipt!(contract.decimals())?),
(totalSupplyCall::SIGNATURE, receipt!(contract.totalSupply())?),
(balanceOfCall::SIGNATURE, receipt!(contract.balanceOf(alice_addr))?),
(allowanceCall::SIGNATURE, receipt!(contract.allowance(alice_addr, bob_addr))?),
(capCall::SIGNATURE, receipt!(contract.cap())?),
(mintCall::SIGNATURE, receipt!(contract.mint(alice_addr, uint!(10_U256)))?),
(burnCall::SIGNATURE, receipt!(contract.burn(uint!(1_U256)))?),
(transferCall::SIGNATURE, receipt!(contract.transfer(bob_addr, uint!(1_U256)))?),
(approveCall::SIGNATURE, receipt!(contract.approve(bob_addr, uint!(5_U256)))?),
(burnFromCall::SIGNATURE, receipt!(contract_bob.burnFrom(alice_addr, uint!(1_U256)))?),
(transferFromCall::SIGNATURE, receipt!(contract_bob.transferFrom(alice_addr, bob_addr, uint!(4_U256)))?),
];

// Calculate the width of the longest function name.
let max_name_width = receipts
.iter()
.max_by_key(|x| x.0.len())
.expect("should at least bench one function")
.0
.len();
let name_width = max_name_width.max("ERC-20".len());

// Calculate the total width of the table.
let total_width = name_width + 3 + 6 + 3 + 6 + 3 + 20 + 4; // 3 for padding, 4 for outer borders

// Print the table header.
println!("+{}+", "-".repeat(total_width - 2));
println!(
"| {:<width$} | L2 Gas | L1 Gas | Effective Gas |",
"ERC-20",
width = name_width
);
println!(
"|{}+--------+--------+----------------------|",
"-".repeat(name_width + 2)
);

// Print each row.
for (func_name, receipt) in receipts {
let l2_gas = receipt.gas_used;
let arb_fields: ArbOtherFields = receipt.other.deserialize_into()?;
let l1_gas = arb_fields.gas_used_for_l1.to::<u128>();
let effective_gas = l2_gas - l1_gas;

println!(
"| {:<width$} | {:>6} | {:>6} | {:>20} |",
func_name,
l2_gas,
l1_gas,
effective_gas,
width = name_width
);
}

// Print the table footer.
println!("+{}+", "-".repeat(total_width - 2));

Ok(())
let report =
receipts.into_iter().try_fold(Report::new("Erc20"), Report::add)?;
Ok(report)
}

async fn deploy(account: &Account) -> Address {
Expand Down
77 changes: 18 additions & 59 deletions benches/src/erc721.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ use alloy::{
primitives::Address,
providers::ProviderBuilder,
sol,
sol_types::SolConstructor,
sol_types::{SolCall, SolConstructor},
uint,
};
use e2e::{receipt, Account};

use crate::ArbOtherFields;
use crate::report::Report;

sol!(
#[sol(rpc)]
Expand All @@ -29,7 +29,7 @@ sol!(

sol!("../examples/erc721/src/constructor.sol");

pub async fn bench() -> eyre::Result<()> {
pub async fn bench() -> eyre::Result<Report> {
let alice = Account::new().await?;
let alice_addr = alice.address();
let alice_wallet = ProviderBuilder::new()
Expand All @@ -54,66 +54,25 @@ pub async fn bench() -> eyre::Result<()> {
let _ = receipt!(contract.mint(alice_addr, token_4))?;

// IMPORTANT: Order matters!
use Erc721::*;
#[rustfmt::skip]
let receipts = vec![
("balanceOf(alice)", receipt!(contract.balanceOf(alice_addr))?),
("approve(bob, 2)", receipt!(contract.approve(bob_addr, token_2))?),
("getApproved(2)", receipt!(contract.getApproved(token_2))?),
("isApprovedForAll(alice, bob)", receipt!(contract.isApprovedForAll(alice_addr, bob_addr))?),
("ownerOf(2)", receipt!(contract.ownerOf(token_2))?),
("safeTransferFrom(alice, bob, 3)", receipt!(contract.safeTransferFrom(alice_addr, bob_addr, token_3))?),
("setApprovalForAll(bob, true)", receipt!(contract.setApprovalForAll(bob_addr, true))?),
("totalSupply()", receipt!(contract.totalSupply())?),
("transferFrom(alice, bob, 4)", receipt!(contract.transferFrom(alice_addr, bob_addr, token_4))?),
("mint(alice, 1)", receipt!(contract.mint(alice_addr, token_1))?),
("burn(1)", receipt!(contract.burn(token_1))?),
(balanceOfCall::SIGNATURE, receipt!(contract.balanceOf(alice_addr))?),
(approveCall::SIGNATURE, receipt!(contract.approve(bob_addr, token_2))?),
(getApprovedCall::SIGNATURE, receipt!(contract.getApproved(token_2))?),
(isApprovedForAllCall::SIGNATURE, receipt!(contract.isApprovedForAll(alice_addr, bob_addr))?),
(ownerOfCall::SIGNATURE, receipt!(contract.ownerOf(token_2))?),
(safeTransferFromCall::SIGNATURE, receipt!(contract.safeTransferFrom(alice_addr, bob_addr, token_3))?),
(setApprovalForAllCall::SIGNATURE, receipt!(contract.setApprovalForAll(bob_addr, true))?),
(totalSupplyCall::SIGNATURE, receipt!(contract.totalSupply())?),
(transferFromCall::SIGNATURE, receipt!(contract.transferFrom(alice_addr, bob_addr, token_4))?),
(mintCall::SIGNATURE, receipt!(contract.mint(alice_addr, token_1))?),
(burnCall::SIGNATURE, receipt!(contract.burn(token_1))?),
];

// Calculate the width of the longest function name.
let max_name_width = receipts
.iter()
.max_by_key(|x| x.0.len())
.expect("should at least bench one function")
.0
.len();
let name_width = max_name_width.max("ERC-721".len());

// Calculate the total width of the table.
let total_width = name_width + 3 + 6 + 3 + 6 + 3 + 20 + 4; // 3 for padding, 4 for outer borders

// Print the table header.
println!("+{}+", "-".repeat(total_width - 2));
println!(
"| {:<width$} | L2 Gas | L1 Gas | Effective Gas |",
"ERC-20",
width = name_width
);
println!(
"|{}+--------+--------+----------------------|",
"-".repeat(name_width + 2)
);

// Print each row.
for (func_name, receipt) in receipts {
let l2_gas = receipt.gas_used;
let arb_fields: ArbOtherFields = receipt.other.deserialize_into()?;
let l1_gas = arb_fields.gas_used_for_l1.to::<u128>();
let effective_gas = l2_gas - l1_gas;

println!(
"| {:<width$} | {:>6} | {:>6} | {:>20} |",
func_name,
l2_gas,
l1_gas,
effective_gas,
width = name_width
);
}

// Print the table footer.
println!("+{}+", "-".repeat(total_width - 2));

Ok(())
let report =
receipts.into_iter().try_fold(Report::new("Erc721"), Report::add)?;
Ok(report)
}

async fn deploy(account: &Account) -> Address {
Expand Down
19 changes: 18 additions & 1 deletion benches/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
use alloy::primitives::Address;
use alloy::{
primitives::Address,
rpc::types::{
serde_helpers::WithOtherFields, AnyReceiptEnvelope, Log,
TransactionReceipt,
},
};
use alloy_primitives::U128;
use e2e::Account;
use koba::config::{Deploy, Generate, PrivateKey};
Expand All @@ -8,6 +14,7 @@ pub mod access_control;
pub mod erc20;
pub mod erc721;
pub mod merkle_proofs;
pub mod report;

const RPC_URL: &str = "http://localhost:8547";

Expand All @@ -20,6 +27,16 @@ struct ArbOtherFields {
l1_block_number: String,
}

type ArbTxReceipt =
WithOtherFields<TransactionReceipt<AnyReceiptEnvelope<Log>>>;

fn get_l2_gas_used(receipt: &ArbTxReceipt) -> eyre::Result<u128> {
let l2_gas = receipt.gas_used;
let arb_fields: ArbOtherFields = receipt.other.deserialize_as()?;
let l1_gas = arb_fields.gas_used_for_l1.to::<u128>();
Ok(l2_gas - l1_gas)
}

async fn deploy(
account: &Account,
contract_name: &str,
Expand Down
10 changes: 8 additions & 2 deletions benches/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
use benches::{access_control, erc20, erc721, merkle_proofs};
use benches::{access_control, erc20, erc721, merkle_proofs, report::Reports};

#[tokio::main]
async fn main() -> eyre::Result<()> {
let _ = tokio::join!(
let reports = tokio::join!(
access_control::bench(),
erc20::bench(),
erc721::bench(),
merkle_proofs::bench()
);

let reports = [reports.0?, reports.1?, reports.2?, reports.3?];
let report =
reports.into_iter().fold(Reports::default(), Reports::merge_with);

println!("{report}");

Ok(())
}
Loading

0 comments on commit a2cb3c6

Please sign in to comment.