Skip to content

Commit

Permalink
Unify the activation fee bump
Browse files Browse the repository at this point in the history
Now the deploy and activate commands have the same option to set the
activation fee bump value.
  • Loading branch information
gligneul committed Nov 8, 2024
1 parent a01ae4d commit b4bd15a
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 55 deletions.
32 changes: 7 additions & 25 deletions main/src/activate.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
// Copyright 2023-2024, Offchain Labs, Inc.
// For licensing, see https://github.com/OffchainLabs/cargo-stylus/blob/stylus/licenses/COPYRIGHT.md

use crate::check::check_activate;
use crate::constants::ARB_WASM_H160;
use crate::macros::greyln;
use crate::util::color::{Color, DebugColor};
use crate::util::sys;
use crate::ActivateConfig;
use alloy_primitives::Address;
use alloy_sol_macro::sol;
use alloy_sol_types::SolCall;
use ethers::middleware::{Middleware, SignerMiddleware};
use ethers::signers::Signer;
use ethers::types::transaction::eip2718::TypedTransaction;
use ethers::types::{Eip1559TransactionRequest, U256};
use ethers::types::Eip1559TransactionRequest;
use ethers::utils::format_units;
use eyre::{bail, Context, Result};

use crate::check::check_activate;
use crate::constants::ARB_WASM_H160;
use crate::macros::greyln;

use crate::ActivateConfig;

sol! {
interface ArbWasm {
function activateProgram(address program)
Expand All @@ -41,25 +39,14 @@ pub async fn activate_contract(cfg: &ActivateConfig) -> Result<()> {
let client = SignerMiddleware::new(provider.clone(), wallet);

let code = client.get_code(cfg.address, None).await?;
let data_fee = check_activate(code, cfg.address, &provider).await?;
let mut data_fee = alloy_ethers_typecast::alloy_u256_to_ethers(data_fee);

greyln!(
"obtained estimated activation data fee {}",
format_units(data_fee, "ether")?.debug_lavender()
);
greyln!(
"bumping estimated activation data fee by {}%",
cfg.data_fee_bump_percent.debug_lavender()
);
data_fee = bump_data_fee(data_fee, cfg.data_fee_bump_percent);
let data_fee = check_activate(code, cfg.address, &cfg.data_fee, &provider).await?;

let contract: Address = cfg.address.to_fixed_bytes().into();
let data = ArbWasm::activateProgramCall { program: contract }.abi_encode();
let tx = Eip1559TransactionRequest::new()
.from(client.address())
.to(*ARB_WASM_H160)
.value(data_fee)
.value(alloy_ethers_typecast::alloy_u256_to_ethers(data_fee))
.data(data);
let tx = TypedTransaction::Eip1559(tx);
if cfg.estimate_gas {
Expand Down Expand Up @@ -96,8 +83,3 @@ pub async fn activate_contract(cfg: &ActivateConfig) -> Result<()> {
}
Ok(())
}

fn bump_data_fee(fee: U256, pct: u64) -> U256 {
let num = 100 + pct;
fee * U256::from(num) / U256::from(100)
}
44 changes: 29 additions & 15 deletions main/src/check.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// Copyright 2023-2024, Offchain Labs, Inc.
// For licensing, see https://github.com/OffchainLabs/cargo-stylus/blob/main/licenses/COPYRIGHT.md

use crate::util::{color::Color, sys, text};
use crate::{
check::ArbWasm::ArbWasmErrors,
constants::{ARB_WASM_H160, ONE_ETH, TOOLCHAIN_FILE_NAME},
macros::*,
project::{self, extract_toolchain_channel, BuildConfig},
CheckConfig,
util::{color::Color, sys, text},
CheckConfig, DataFeeOpts,
};
use alloy_primitives::{Address, B256, U256};
use alloy_sol_macro::sol;
Expand Down Expand Up @@ -87,9 +87,7 @@ pub async fn check(cfg: &CheckConfig) -> Result<ContractCheck> {
}

let address = cfg.contract_address.unwrap_or(H160::random());
let fee = check_activate(code.clone().into(), address, &provider).await?;
let visual_fee = format_data_fee(fee).unwrap_or("???".red());
greyln!("wasm data fee: {visual_fee} ETH");
let fee = check_activate(code.clone().into(), address, &cfg.data_fee, &provider).await?;
Ok(ContractCheck::Ready { code, fee })
}

Expand All @@ -112,7 +110,7 @@ impl ContractCheck {
pub fn suggest_fee(&self) -> U256 {
match self {
Self::Active { .. } => U256::default(),
Self::Ready { fee, .. } => fee * U256::from(120) / U256::from(100),
Self::Ready { fee, .. } => *fee,
}
}
}
Expand Down Expand Up @@ -148,17 +146,19 @@ pub fn format_file_size(len: usize, mid: u64, max: u64) -> String {
}

/// Pretty-prints a data fee.
fn format_data_fee(fee: U256) -> Result<String> {
let fee: u64 = (fee / U256::from(1e9)).try_into()?;
fn format_data_fee(fee: U256) -> String {
let Ok(fee): Result<u64, _> = (fee / U256::from(1e9)).try_into() else {
return ("???").red();
};
let fee: f64 = fee as f64 / 1e9;
let text = format!("{fee:.6}");
Ok(if fee <= 5e14 {
let text = format!("{fee:.6} ETH");
if fee <= 5e14 {
text.mint()
} else if fee <= 5e15 {
text.yellow()
} else {
text.pink()
})
}
}

pub struct EthCallError {
Expand Down Expand Up @@ -247,7 +247,12 @@ Perhaps the Arbitrum node for the endpoint you are connecting to has not yet upg
}

/// Checks contract activation, returning the data fee.
pub async fn check_activate(code: Bytes, address: H160, provider: &Provider<Http>) -> Result<U256> {
pub async fn check_activate(
code: Bytes,
address: H160,
opts: &DataFeeOpts,
provider: &Provider<Http>,
) -> Result<U256> {
let contract = Address::from(address.to_fixed_bytes());
let data = ArbWasm::activateProgramCall { program: contract }.abi_encode();
let tx = Eip1559TransactionRequest::new()
Expand All @@ -256,8 +261,17 @@ pub async fn check_activate(code: Bytes, address: H160, provider: &Provider<Http
.value(ONE_ETH);
let state = spoof::code(address, code);
let outs = eth_call(tx, state, provider).await??;
let ArbWasm::activateProgramReturn { dataFee, .. } =
ArbWasm::activateProgramCall::abi_decode_returns(&outs, true)?;
let ArbWasm::activateProgramReturn {
dataFee: data_fee, ..
} = ArbWasm::activateProgramCall::abi_decode_returns(&outs, true)?;

let bump = opts.data_fee_bump_percent;
let adjusted_data_fee = data_fee * U256::from(100 + bump) / U256::from(100);
print!("{}", "wasm data fee: ".grey());
print!("{}", format_data_fee(adjusted_data_fee));
print!("{}", " (originally ".grey());
print!("{}", format_data_fee(data_fee));
greyln!(" with {bump}% bump)");

Ok(dataFee)
Ok(adjusted_data_fee)
}
21 changes: 10 additions & 11 deletions main/src/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,18 @@ pub async fn deploy(cfg: DeployConfig) -> Result<()> {
return Ok(());
}

if cfg.no_activate {
mintln!(
r#"NOTE: You must activate the stylus contract before calling it. To do so, we recommend running:
cargo stylus activate --address {}"#,
hex::encode(contract_addr)
);
return Ok(());
}

match contract {
ContractCheck::Ready { .. } => {
cfg.activate(sender, contract_addr, data_fee, &client)
.await?
if cfg.no_activate {
mintln!(
r#"NOTE: You must activate the stylus contract before calling it. To do so, we recommend running:
cargo stylus activate --address {}"#,
hex::encode(contract_addr)
);
} else {
cfg.activate(sender, contract_addr, data_fee, &client)
.await?
}
}
ContractCheck::Active { .. } => greyln!("wasm already activated!"),
}
Expand Down
14 changes: 11 additions & 3 deletions main/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,15 +181,14 @@ pub struct CacheSuggestionsConfig {
pub struct ActivateConfig {
#[command(flatten)]
common_cfg: CommonConfig,
#[command(flatten)]
data_fee: DataFeeOpts,
/// Wallet source to use.
#[command(flatten)]
auth: AuthOpts,
/// Deployed Stylus contract address to activate.
#[arg(long)]
address: H160,
/// Percent to bump the estimated activation data fee by. Default of 20%
#[arg(long, default_value = "20")]
data_fee_bump_percent: u64,
/// Whether or not to just estimate gas without sending a tx.
#[arg(long)]
estimate_gas: bool,
Expand All @@ -199,6 +198,8 @@ pub struct ActivateConfig {
pub struct CheckConfig {
#[command(flatten)]
common_cfg: CommonConfig,
#[command(flatten)]
data_fee: DataFeeOpts,
/// The WASM to check (defaults to any found in the current directory).
#[arg(long)]
wasm_file: Option<PathBuf>,
Expand Down Expand Up @@ -314,6 +315,13 @@ pub struct SimulateArgs {
use_native_tracer: bool,
}

#[derive(Clone, Debug, Args)]
struct DataFeeOpts {
/// Percent to bump the estimated activation data fee by.
#[arg(long, default_value = "20")]
data_fee_bump_percent: u64,
}

#[derive(Clone, Debug, Args)]
#[clap(group(ArgGroup::new("key").required(true).args(&["private_key_path", "private_key", "keystore_path"])))]
struct AuthOpts {
Expand Down
5 changes: 4 additions & 1 deletion main/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{
constants::TOOLCHAIN_FILE_NAME,
deploy::{self, extract_compressed_wasm, extract_contract_evm_deployment_prelude},
project::{self, extract_toolchain_channel},
CheckConfig, VerifyConfig,
CheckConfig, DataFeeOpts, VerifyConfig,
};

#[derive(Debug, Deserialize, Serialize)]
Expand Down Expand Up @@ -52,6 +52,9 @@ pub async fn verify(cfg: VerifyConfig) -> eyre::Result<()> {
}
let check_cfg = CheckConfig {
common_cfg: cfg.common_cfg.clone(),
data_fee: DataFeeOpts {
data_fee_bump_percent: 20,
},
wasm_file: None,
contract_address: None,
};
Expand Down

0 comments on commit b4bd15a

Please sign in to comment.