diff --git a/.github/workflows/account_deployment.yml b/.github/workflows/account_deployment.yml new file mode 100644 index 00000000..39c75652 --- /dev/null +++ b/.github/workflows/account_deployment.yml @@ -0,0 +1,28 @@ +name: account-deployment +on: + schedule: + interval: "monthly" + +env: + RUSTFLAGS: -D warnings + RUST_BACKTRACE: 1 + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + test: + if: ${{ !startsWith(github.head_ref, 'dependabot/') }} + runs-on: ubuntu-latest + env: + BEERUS_TEST_RUN: 1 + STARKNET_SEPOLIA_URL: https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_7/${{ secrets.ALCHEMY_KEY }} + ACCOUNT_ADDRESS: ${{secrets.ACCOUNT_ADDRESS}} + PRIVATE_KEY: ${{secrets.PRIVATE_KEY}} + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - run: rm -rf /opt/hostedtoolcache + - run: cargo test deploy_account_on_sepolia diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 51eed499..9f498409 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -35,7 +35,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - run: rm -rf /opt/hostedtoolcache - - run: cargo test + - run: cargo test -- --skip deploy_account_on_sepolia wasm: runs-on: ubuntu-latest diff --git a/tests/account_katana.rs b/tests/account_katana.rs index d79f3a22..3db4a2a8 100644 --- a/tests/account_katana.rs +++ b/tests/account_katana.rs @@ -1,6 +1,5 @@ use std::{sync::Arc, thread, time}; -use ::starknet::core::types::PriceUnit; use beerus::{ client::{Http, State}, gen::{ @@ -83,9 +82,7 @@ async fn deploy_account_on_katana() -> Result<(), Error> { let class_hash = starkli.extract_class_hash()?; let address = starkli.create_account(key.clone(), class_hash).await?; starkli.declare_account().await?; - starkli - .invoke_eth_transfer(address, 5000000000000000000, PriceUnit::Wei) - .await?; + starkli.invoke_eth_transfer(address, 5e18 as u64).await?; starkli.deploy_account().await?; // Redirect starkli to katana in verification because katana does not support diff --git a/tests/common/ctx.rs b/tests/common/ctx.rs index 2e840687..37474c00 100644 --- a/tests/common/ctx.rs +++ b/tests/common/ctx.rs @@ -37,13 +37,13 @@ pub async fn ctx_sepolia() -> Option { let url = std::env::var("STARKNET_SEPOLIA_URL").ok()?; let state = State { - block_number: 209582, + block_number: 293268, block_hash: Felt::try_new( - "0x45fb3ae1436743e74a81eac88e1beee6e8fb34aecb7b2e43e0577406f390f5f", + "0x7799ec4953a1786e59e5ad02b4576cd59fa3b9efa059b7d56a9eb2b6ad6f2e", ) .unwrap(), root: Felt::try_new( - "0x11dccdce33557ca6e14871d4235a8b65e9bd512722ac9e2cb96ff49bfb9af30", + "0x54882b0dcb575e5e18bfac4c22b00f0cadcd83885d8c35b0b9d6e0e125ce3be", ) .unwrap(), }; diff --git a/tests/rpc.rs b/tests/rpc.rs index ddb7190f..13922910 100644 --- a/tests/rpc.rs +++ b/tests/rpc.rs @@ -1,3 +1,5 @@ +use std::{thread, time}; + use beerus::{ config::MAINNET_STARKNET_CHAINID, gen::{ @@ -15,6 +17,11 @@ mod common; mod starknet; use common::err::Error; +use starknet::{ + scarb, + starkli::{PreFundedAccount, Starkli}, + utils, +}; #[tokio::test] #[allow(non_snake_case)] @@ -533,3 +540,47 @@ async fn account_call() -> Result<(), Error> { Ok(()) } + +#[tokio::test] +async fn deploy_account_on_sepolia() -> Result<(), Error> { + let ctx = setup!("sepolia"); + + let account = utils::prepare_account()?; + scarb::compile_blocking(account.toml).await?; + + let mut starkli = Starkli::new( + &format!("http://127.0.0.1:{}/rpc", ctx.server.port()), + &account.folder, + PreFundedAccount::Sepolia, + ); + let key = starkli.create_keystore()?; + let class_hash = starkli.extract_class_hash()?; + let address = starkli.create_account(key.clone(), class_hash).await?; + starkli.declare_account().await?; + + let time_for_transaction_validation = time::Duration::from_secs(60); + thread::sleep(time_for_transaction_validation); + + // Usual account deployment fee is ~1e9 + // Added additional eth just to be safe + let amount_to_transfer = 1e12 as u64; + starkli.invoke_eth_transfer(address, amount_to_transfer).await?; + + thread::sleep(time_for_transaction_validation); + starkli.deploy_account().await?; + + // Unable to verify via beerus due to hard coded L1 state + // and time for newly created account to arrive on L1 + starkli.rpc = std::env::var("STARKNET_SEPOLIA_URL").ok().unwrap(); + + let res_id = starkli.call(address, "id").await?; + assert_eq!(res_id.len(), 2); + assert_eq!(res_id[0].to_string(), account.id); + assert_eq!(res_id[1], starknet_crypto::Felt::ZERO); + + let res_public_key = starkli.call(address, "public_key").await?; + assert_eq!(res_public_key.len(), 1); + assert_eq!(res_public_key[0], key.verifying_key().scalar()); + + Ok(()) +} diff --git a/tests/starknet/starkli.rs b/tests/starknet/starkli.rs index 60199412..611bf6f7 100644 --- a/tests/starknet/starkli.rs +++ b/tests/starknet/starkli.rs @@ -11,7 +11,7 @@ use starkli::{ utils::{Cli, Subcommands}, }; use starknet::{ - core::types::{contract::SierraClass, PriceUnit}, + core::types::contract::SierraClass, signers::{LocalWallet, Signer, SigningKey}, }; use starknet_crypto::Felt; @@ -20,7 +20,7 @@ use starknet_crypto::Felt; pub struct Starkli { pub rpc: String, account_folder: String, - prefunded_account: String, + prefunded_account: PreFundedAccount, persist_logger: bool, } @@ -42,10 +42,6 @@ impl Starkli { account_folder: &str, prefunded_account: PreFundedAccount, ) -> Self { - let prefunded_account = match prefunded_account { - PreFundedAccount::Katana => "katana-0".to_string(), - PreFundedAccount::Sepolia => unimplemented!(), - }; Self { rpc: rpc.into(), account_folder: account_folder.into(), @@ -101,18 +97,16 @@ impl Starkli { pub async fn declare_account(&mut self) -> Result<(), Error> { let compiled_contract = self.account_folder.clone() + COMPILED_ACCOUNT; let rpc = self.rpc.clone(); - let account = self.prefunded_account.clone(); - let input = vec![ - "starkli", - "declare", - &compiled_contract, - "--compiler-version", - "2.8.2", - "--rpc", - &rpc, - "--account", - &account, + let mut input = vec![ + "starkli".to_string(), + "declare".to_string(), + compiled_contract, + "--compiler-version".to_string(), + "2.8.2".to_string(), + "--rpc".to_string(), + rpc, ]; + self.setup_prefunded_account(&mut input); self.run_command(input).await } @@ -120,29 +114,21 @@ impl Starkli { &mut self, to_address: Felt, amount: u64, - unit: PriceUnit, ) -> Result<(), Error> { - let address = &format!("{:#064x}", to_address); - let amount = &format!("u256:{amount}"); - let unit = match unit { - PriceUnit::Wei => "--eth", - PriceUnit::Fri => "--strk", - }; + let address = format!("{:#064x}", to_address); + let amount = format!("u256:{amount}"); let rpc = self.rpc.clone(); - let account = self.prefunded_account.clone(); - let input = vec![ - "starkli", - "invoke", - unit, - "eth", - "transfer", + let mut input = vec![ + "starkli".to_string(), + "invoke".to_string(), + "eth".to_string(), + "transfer".to_string(), address, amount, - "--rpc", - &rpc, - "--account", - &account, + "--rpc".to_string(), + rpc, ]; + self.setup_prefunded_account(&mut input); self.run_command(input).await } @@ -151,26 +137,50 @@ impl Starkli { let key = self.account_folder.clone() + "key.json"; let rpc = self.rpc.clone(); let input = vec![ - "starkli", - "account", - "deploy", - &account, - "--rpc", - &rpc, - "--keystore", - &key, - "--keystore-password", - "password", - "--skip-manual-confirmation", + "starkli".to_string(), + "account".to_string(), + "deploy".to_string(), + account, + "--rpc".to_string(), + rpc, + "--keystore".to_string(), + key, + "--keystore-password".to_string(), + "password".to_string(), + "--skip-manual-confirmation".to_string(), ]; self.run_command(input).await } - async fn run_command(&mut self, mut input: Vec<&str>) -> Result<(), Error> { + fn setup_prefunded_account(&self, input: &mut Vec) { + match self.prefunded_account { + PreFundedAccount::Katana => { + input.append(&mut vec![ + "--account".to_string(), + "katana-0".to_string(), + ]); + } + PreFundedAccount::Sepolia => { + let account = std::env::var("DEPLOYER_ACCOUNT").unwrap(); + let private_key = std::env::var("PRIVATE_KEY").unwrap(); + input.append(&mut vec![ + "--account".to_string(), + account.to_string(), + "--private-key".to_string(), + private_key.to_string(), + ]); + } + } + } + + async fn run_command( + &mut self, + mut input: Vec, + ) -> Result<(), Error> { if !self.persist_logger { self.persist_logger = true; } else { - input.push("--persist-logger"); + input.push("--persist-logger".to_string()); } starkli::utils::run_command(Cli::parse_from(input)).await }