Skip to content

Commit 7e4ba6b

Browse files
authored
Use strk as a default fee token (#2749)
<!-- Reference any GitHub issues resolved by this PR --> Closes #2696 ## Introduced changes <!-- A brief description of the changes --> - ## Checklist <!-- Make sure all of these are complete --> - [x] Linked relevant issue - [x] Updated relevant documentation - [x] Added relevant tests - [x] Performed self-review of the code - [x] Added changes to `CHANGELOG.md`
1 parent 3b71dd4 commit 7e4ba6b

File tree

20 files changed

+171
-112
lines changed

20 files changed

+171
-112
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616

1717
#### Changed
1818

19-
- `snforge_scarb_plugin` will now also emit warnings when errors occur
19+
- `snforge_scarb_plugin` will now also emit warnings when errors occur
20+
21+
### Cast
22+
23+
#### Deprecated
24+
25+
- `--fee-token` and `--version` flags are now optional, `strk` and `v3` will be used by default
2026

2127
## [0.34.0] - 2024-11-26
2228

crates/sncast/src/helpers/fee.rs

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
use anyhow::{bail, ensure, Result};
1+
use anyhow::{bail, ensure, Error, Result};
22
use clap::{Args, ValueEnum};
33
use conversions::serde::deserialize::CairoDeserialize;
44
use conversions::TryIntoConv;
5+
use shared::print::print_as_warning;
56
use starknet::core::types::BlockId;
67
use starknet::providers::Provider;
78
use starknet_types_core::felt::{Felt, NonZeroFelt};
9+
use std::str::FromStr;
810

911
#[derive(Args, Debug, Clone)]
1012
pub struct FeeArgs {
1113
/// Token that transaction fee will be paid in
12-
#[clap(long)]
14+
#[clap(long, value_parser = parse_fee_token)]
1315
pub fee_token: Option<FeeToken>,
1416

1517
/// Max fee for the transaction. If not provided, will be automatically estimated.
@@ -50,9 +52,9 @@ impl From<ScriptFeeSettings> for FeeArgs {
5052

5153
impl FeeArgs {
5254
#[must_use]
53-
pub fn fee_token(self, fee_token: Option<FeeToken>) -> Self {
55+
pub fn fee_token(self, fee_token: FeeToken) -> Self {
5456
Self {
55-
fee_token: fee_token.or(self.fee_token),
57+
fee_token: Some(fee_token),
5658
..self
5759
}
5860
}
@@ -138,9 +140,10 @@ impl FeeArgs {
138140
}
139141
}
140142

141-
#[derive(ValueEnum, Debug, Clone, PartialEq)]
143+
#[derive(ValueEnum, Default, Debug, Clone, PartialEq)]
142144
pub enum FeeToken {
143145
Eth,
146+
#[default]
144147
Strk,
145148
}
146149

@@ -187,7 +190,7 @@ impl From<ScriptFeeSettings> for FeeSettings {
187190

188191
pub trait PayableTransaction {
189192
fn error_message(&self, token: &str, version: &str) -> String;
190-
fn validate(&self) -> Result<()>;
193+
fn validate_and_get_token(&self) -> Result<FeeToken>;
191194
fn token_from_version(&self) -> Option<FeeToken>;
192195
}
193196

@@ -199,21 +202,27 @@ macro_rules! impl_payable_transaction {
199202
$err_func(token, version)
200203
}
201204

202-
fn validate(&self) -> Result<()> {
205+
fn validate_and_get_token(&self) -> Result<FeeToken> {
203206
match (
204207
&self.token_from_version(),
205208
&self.fee_args.fee_token,
206209
) {
207210
(Some(token_from_version), Some(token)) if token_from_version != token => {
208211
Err(anyhow!(self.error_message(
209-
&format!("{token:?}").to_lowercase(),
212+
&format!("{:?}", token).to_lowercase(),
210213
&format!("{:?}", self.version.clone().unwrap()).to_lowercase()
211214
)))
212-
}
215+
},
216+
(None, Some(token)) => {
217+
Ok(token.clone())
218+
},
219+
(Some(token_from_version), None) => {
220+
Ok(token_from_version.clone())
221+
},
213222
(None, None) => {
214-
Err(anyhow!("Either --fee-token or --version must be provided"))
215-
}
216-
_ => Ok(()),
223+
Ok(FeeToken::default())
224+
},
225+
_ => Ok(self.fee_args.fee_token.clone().unwrap_or_else(|| self.token_from_version().unwrap_or_else(|| unreachable!())))
217226
}
218227
}
219228

@@ -225,3 +234,30 @@ macro_rules! impl_payable_transaction {
225234
}
226235
};
227236
}
237+
238+
impl FromStr for FeeToken {
239+
type Err = String;
240+
241+
fn from_str(s: &str) -> Result<Self, Self::Err> {
242+
match s.to_lowercase().as_str() {
243+
"eth" => Ok(FeeToken::Eth),
244+
"strk" => Ok(FeeToken::Strk),
245+
_ => Err(String::from("Possible values: eth, strk")),
246+
}
247+
}
248+
}
249+
250+
fn parse_fee_token(s: &str) -> Result<FeeToken, String> {
251+
let deprecation_message = "Specifying '--fee-token' flag is deprecated and will be removed in the future. Use '--version' instead";
252+
print_as_warning(&Error::msg(deprecation_message));
253+
254+
let parsed_token: FeeToken = s.parse()?;
255+
256+
if parsed_token == FeeToken::Eth {
257+
print_as_warning(&Error::msg(
258+
"Eth transactions will stop being supported in the future due to 'SNIP-16'",
259+
));
260+
}
261+
262+
Ok(parsed_token)
263+
}

crates/sncast/src/main.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ async fn run_async_command(
235235
Commands::Declare(declare) => {
236236
let provider = declare.rpc.get_provider(&config).await?;
237237

238-
declare.validate()?;
238+
let fee_token = declare.validate_and_get_token()?;
239239

240240
let account = get_account(
241241
&config.account,
@@ -262,6 +262,7 @@ async fn run_async_command(
262262
&artifacts,
263263
wait_config,
264264
false,
265+
fee_token,
265266
)
266267
.await
267268
.map_err(handle_starknet_command_error)
@@ -286,9 +287,7 @@ async fn run_async_command(
286287
}
287288

288289
Commands::Deploy(deploy) => {
289-
deploy.validate()?;
290-
291-
let fee_token = deploy.token_from_version();
290+
let fee_token = deploy.validate_and_get_token()?;
292291

293292
let Deploy {
294293
arguments,
@@ -378,9 +377,7 @@ async fn run_async_command(
378377
}
379378

380379
Commands::Invoke(invoke) => {
381-
invoke.validate()?;
382-
383-
let fee_token = invoke.token_from_version();
380+
let fee_token = invoke.validate_and_get_token()?;
384381

385382
let Invoke {
386383
contract_address,
@@ -457,8 +454,6 @@ async fn run_async_command(
457454
starknet_commands::multicall::Commands::Run(run) => {
458455
let provider = run.rpc.get_provider(&config).await?;
459456

460-
run.validate()?;
461-
462457
let account = get_account(
463458
&config.account,
464459
&config.accounts_file,
@@ -533,10 +528,12 @@ async fn run_async_command(
533528
}
534529

535530
account::Commands::Deploy(deploy) => {
536-
deploy.validate()?;
537-
538531
let provider = deploy.rpc.get_provider(&config).await?;
539532

533+
let fee_token = deploy.validate_and_get_token()?;
534+
535+
let fee_args = deploy.fee_args.clone().fee_token(fee_token);
536+
540537
let chain_id = get_chain_id(&provider).await?;
541538
let keystore_path = config.keystore.clone();
542539
let result = starknet_commands::account::deploy::deploy(
@@ -547,6 +544,7 @@ async fn run_async_command(
547544
wait_config,
548545
&config.account,
549546
keystore_path,
547+
fee_args,
550548
)
551549
.await;
552550

crates/sncast/src/starknet_commands/account/deploy.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,8 @@ pub async fn deploy(
6565
wait_config: WaitForTx,
6666
account: &str,
6767
keystore_path: Option<Utf8PathBuf>,
68+
fee_args: FeeArgs,
6869
) -> Result<InvokeResponse> {
69-
let fee_args = deploy_args
70-
.fee_args
71-
.clone()
72-
.fee_token(deploy_args.token_from_version());
73-
7470
if let Some(keystore_path_) = keystore_path {
7571
deploy_from_keystore(
7672
provider,

crates/sncast/src/starknet_commands/declare.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,12 @@ pub async fn declare(
6969
artifacts: &HashMap<String, StarknetContractArtifacts>,
7070
wait_config: WaitForTx,
7171
skip_on_already_declared: bool,
72+
fee_token: FeeToken,
7273
) -> Result<DeclareResponse, StarknetCommandError> {
7374
let fee_settings = declare
7475
.fee_args
7576
.clone()
76-
.fee_token(declare.token_from_version())
77+
.fee_token(fee_token)
7778
.try_into_fee_settings(account.provider(), account.block_id())
7879
.await?;
7980

crates/sncast/src/starknet_commands/multicall/run.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ pub async fn run(
7171
account: &SingleOwnerAccount<&JsonRpcClient<HttpTransport>, LocalWallet>,
7272
wait_config: WaitForTx,
7373
) -> Result<InvokeResponse> {
74-
let fee_args = run.fee_args.clone().fee_token(run.token_from_version());
74+
let fee_token = run.validate_and_get_token()?;
75+
76+
let fee_args = run.fee_args.clone().fee_token(fee_token);
7577

7678
let contents = std::fs::read_to_string(&run.path)?;
7779
let items_map: HashMap<String, Vec<toml::Value>> =

crates/sncast/src/starknet_commands/script/run.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use shared::utils::build_readable_text;
3535
use sncast::get_nonce;
3636
use sncast::helpers::configuration::CastConfig;
3737
use sncast::helpers::constants::SCRIPT_LIB_ARTIFACT_NAME;
38-
use sncast::helpers::fee::{FeeSettings, ScriptFeeSettings};
38+
use sncast::helpers::fee::{FeeArgs, FeeSettings, ScriptFeeSettings};
3939
use sncast::helpers::rpc::RpcArgs;
4040
use sncast::response::structs::ScriptRunResponse;
4141
use sncast::state::hashing::{
@@ -116,7 +116,8 @@ impl<'a> ExtensionLogic for CastScriptExtension<'a> {
116116
}
117117
"declare" => {
118118
let contract: String = input_reader.read::<ByteArray>()?.to_string();
119-
let fee_args = input_reader.read::<ScriptFeeSettings>()?.into();
119+
let fee_args: FeeArgs = input_reader.read::<ScriptFeeSettings>()?.into();
120+
let fee_token = fee_args.fee_token.clone().unwrap_or_default();
120121
let nonce = input_reader.read()?;
121122

122123
let declare = Declare {
@@ -145,6 +146,7 @@ impl<'a> ExtensionLogic for CastScriptExtension<'a> {
145146
wait_params: self.config.wait_params,
146147
},
147148
true,
149+
fee_token,
148150
));
149151

150152
self.state.maybe_insert_tx_entry(

crates/sncast/tests/e2e/account/deploy.rs

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ async fn test_invalid_version_and_token_combination(fee_token: &str, version: &s
349349
}
350350

351351
#[tokio::test]
352-
async fn test_no_version_and_token() {
352+
async fn test_default_fee_token() {
353353
let tempdir = create_account(false, &OZ_CLASS_HASH.into_hex_string(), "oz").await;
354354
let accounts_file = "accounts.json";
355355

@@ -367,11 +367,79 @@ async fn test_no_version_and_token() {
367367

368368
let snapbox = runner(&args).current_dir(tempdir.path());
369369

370-
let output = snapbox.assert().failure();
371-
assert_stderr_contains(
372-
output,
373-
"Error: Either --fee-token or --version must be provided",
374-
);
370+
snapbox.assert().success().stdout_matches(indoc! {r"
371+
Transaction hash: [..]
372+
command: account deploy
373+
transaction_hash: [..]
374+
375+
To see invocation details, visit:
376+
transaction: [..]
377+
"});
378+
}
379+
380+
#[tokio::test]
381+
async fn test_fee_token_deprecation_warning_eth() {
382+
let tempdir = create_account(false, &OZ_CLASS_HASH.into_hex_string(), "oz").await;
383+
let accounts_file = "accounts.json";
384+
385+
let args = vec![
386+
"--accounts-file",
387+
accounts_file,
388+
"--wait",
389+
"account",
390+
"deploy",
391+
"--url",
392+
URL,
393+
"--name",
394+
"my_account",
395+
"--fee-token",
396+
"eth",
397+
];
398+
399+
let snapbox = runner(&args).current_dir(tempdir.path());
400+
401+
snapbox.assert().success().stdout_matches(indoc! {r"
402+
[WARNING] Specifying '--fee-token' flag is deprecated and will be removed in the future. Use '--version' instead
403+
[WARNING] Eth transactions will stop being supported in the future due to 'SNIP-16'
404+
Transaction hash: [..]
405+
command: account deploy
406+
transaction_hash: [..]
407+
408+
To see invocation details, visit:
409+
transaction: [..]
410+
"});
411+
}
412+
413+
#[tokio::test]
414+
async fn test_fee_token_deprecation_warning_strk() {
415+
let tempdir = create_account(false, &OZ_CLASS_HASH.into_hex_string(), "oz").await;
416+
let accounts_file = "accounts.json";
417+
418+
let args = vec![
419+
"--accounts-file",
420+
accounts_file,
421+
"--wait",
422+
"account",
423+
"deploy",
424+
"--url",
425+
URL,
426+
"--name",
427+
"my_account",
428+
"--fee-token",
429+
"strk",
430+
];
431+
432+
let snapbox = runner(&args).current_dir(tempdir.path());
433+
434+
snapbox.assert().success().stdout_matches(indoc! {r"
435+
[WARNING] Specifying '--fee-token' flag is deprecated and will be removed in the future. Use '--version' instead
436+
Transaction hash: [..]
437+
command: account deploy
438+
transaction_hash: [..]
439+
440+
To see invocation details, visit:
441+
transaction: [..]
442+
"});
375443
}
376444

377445
#[tokio::test]
@@ -390,8 +458,6 @@ pub async fn test_valid_class_hash() {
390458
"my_account",
391459
"--max-fee",
392460
"10000000000000000",
393-
"--fee-token",
394-
"eth",
395461
];
396462

397463
let snapbox = runner(&args).current_dir(tempdir.path());
@@ -421,8 +487,6 @@ pub async fn test_valid_no_max_fee() {
421487
URL,
422488
"--name",
423489
"my_account",
424-
"--fee-token",
425-
"eth",
426490
];
427491

428492
let snapbox = runner(&args).current_dir(tempdir.path());
@@ -515,8 +579,6 @@ pub async fn test_happy_case_keystore(account_type: &str) {
515579
URL,
516580
"--max-fee",
517581
"99999999999999999",
518-
"--fee-token",
519-
"eth",
520582
];
521583

522584
let snapbox = runner(&args).current_dir(tempdir.path());
@@ -791,8 +853,6 @@ pub async fn test_deploy_keystore_other_args() {
791853
"some-name",
792854
"--max-fee",
793855
"99999999999999999",
794-
"--fee-token",
795-
"eth",
796856
];
797857

798858
let snapbox = runner(&args).current_dir(tempdir.path());

0 commit comments

Comments
 (0)