Skip to content

Commit

Permalink
test: scarb library with template test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
ICavlek committed Oct 15, 2024
1 parent fd92119 commit e44e531
Show file tree
Hide file tree
Showing 22 changed files with 2,139 additions and 65 deletions.
1,764 changes: 1,745 additions & 19 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ katana-node = { git = "https://github.com/dojoengine/dojo", tag = "v1.0.0-alpha.
katana-primitives = { git = "https://github.com/dojoengine/dojo", tag = "v1.0.0-alpha.9" }
katana-rpc = { git = "https://github.com/dojoengine/dojo", tag = "v1.0.0-alpha.9" }
katana-rpc-api = { git = "https://github.com/dojoengine/dojo", tag = "v1.0.0-alpha.9" }
scarb = { git = "https://github.com/software-mansion/scarb/", tag = "v2.8.3" }
semver = { version = "1", features = ["serde"] }
wiremock = "0.6.2"

[patch.crates-io]
Expand Down
24 changes: 20 additions & 4 deletions tests/account_katana.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ use beerus::{
TxnHash,
},
};
use common::constants::{
CLASS_HASH, COMPILED_ACCOUNT_CONTRACT_V2, COMPILED_ACCOUNT_CONTRACT_V3,
CONTRACT_ADDRESS, DECLARE_ACCOUNT_V2, DECLARE_ACCOUNT_V3, SENDER_ADDRESS,
use common::err::Error;
use starknet::katana::Katana;
use starknet::{
constants::{
CLASS_HASH, COMPILED_ACCOUNT_CONTRACT_V2, COMPILED_ACCOUNT_CONTRACT_V3,
CONTRACT_ADDRESS, DECLARE_ACCOUNT_V2, DECLARE_ACCOUNT_V3,
SENDER_ADDRESS,
},
executor::Executor,
};
use common::katana::Katana;

mod common;
mod starknet;

async fn setup() -> (Katana, Client<Http>) {
let katana = Katana::init("http://127.0.0.1:0").await.unwrap();
Expand All @@ -41,6 +47,16 @@ async fn declare_deploy_account_v2() {
deploy(client).await;
}

#[tokio::test]
async fn deploy_multiple_accounts_on_katana() -> Result<(), Error> {
let _katana = Katana::init("http://127.0.0.1:0").await?;
let num_of_new_accounts = 3;
let mut executor = Executor::new(num_of_new_accounts)?;
let update_template = false;
executor.deploy_accounts(update_template)?;
Ok(())
}

async fn declare(
client: &Client<Http>,
compiled_contract: &str,
Expand Down
4 changes: 2 additions & 2 deletions tests/account_mock.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use beerus::gen::{Address, BlockId, BlockTag, Felt, Rpc, TxnHash};

use common::{
use mock::{
dummies::{
declare_transaction, deploy_transaction, estimate_fee_transaction,
invoke_transaction,
Expand All @@ -15,7 +15,7 @@ use common::{
node::setup_client_with_mock_starknet_node,
};

mod common;
mod mock;

#[tokio::test]
async fn chain_id_test() {
Expand Down
4 changes: 4 additions & 0 deletions tests/common/err.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ pub enum Error {
Json(#[from] serde_json::Error),
#[error("starknet api error: {0:?}")]
Api(#[from] starknet_api::StarknetApiError),
#[error("IO error: {0:?}")]
IO(#[from] std::io::Error),
#[error("Anyhow error: {0:?}")]
Anyhow(#[from] anyhow::Error),
}
5 changes: 0 additions & 5 deletions tests/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,2 @@
pub mod constants;
pub mod ctx;
pub mod dummies;
pub mod err;
pub mod katana;
pub mod matchers;
pub mod node;
File renamed without changes.
File renamed without changes.
3 changes: 3 additions & 0 deletions tests/mock/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod dummies;
pub mod matchers;
pub mod node;
File renamed without changes.
55 changes: 24 additions & 31 deletions tests/rpc.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,18 @@
use beerus::{
config::MAINNET_STARKNET_CHAINID,
gen::{
Address, BlockHash, BlockId, BlockNumber, BlockTag,
BroadcastedInvokeTxn, BroadcastedTxn, Felt, FunctionCall,
GetBlockWithTxHashesResult, GetBlockWithTxsResult, GetClassAtResult,
GetClassResult, GetTransactionByBlockIdAndIndexIndex, InvokeTxn,
InvokeTxnV1, InvokeTxnV1Version, PriceUnit, Rpc, StorageKey,
SyncingResult, Txn, TxnExecutionStatus, TxnHash, TxnReceipt,
TxnReceiptWithBlockInfo, TxnStatus,
},
use beerus::gen::{
Address, BlockHash, BlockId, BlockNumber, BlockTag, BroadcastedInvokeTxn,
BroadcastedTxn, Felt, FunctionCall, GetBlockWithTxHashesResult,
GetBlockWithTxsResult, GetClassAtResult, GetClassResult,
GetTransactionByBlockIdAndIndexIndex, InvokeTxn, InvokeTxnV1,
InvokeTxnV1Version, PriceUnit, Rpc, StorageKey, SyncingResult, Txn,
TxnExecutionStatus, TxnHash, TxnReceipt, TxnReceiptWithBlockInfo,
TxnStatus,
};

mod common;
mod starknet;

use common::err::Error;

#[tokio::test]
#[allow(non_snake_case)]
async fn test_specVersion() -> Result<(), Error> {
let ctx = setup!();

let ret = ctx.client.specVersion().await?;
assert_eq!(ret, "0.7.1");
Ok(())
}

#[tokio::test]
#[allow(non_snake_case)]
async fn test_chainId() -> Result<(), Error> {
let ctx = setup!();

let ret = ctx.client.chainId().await?;
assert_eq!(ret.as_ref(), MAINNET_STARKNET_CHAINID);
Ok(())
}
use starknet::executor::Executor;

#[tokio::test]
#[allow(non_snake_case)]
Expand Down Expand Up @@ -532,3 +511,17 @@ async fn account_call() -> Result<(), Error> {

Ok(())
}

#[tokio::test]
async fn deploy_new_account_on_sepolia() -> Result<(), Error> {
// TODO #807
// schedule test once each month in separate workflow
// with each test, template account id is incremented by 1
// commit from workflows to update latest state of id
let _ctx = setup!("sepolia");
let num_of_new_accounts = 1;
let _executor = Executor::new(num_of_new_accounts)?;
let _update_template = true;
// executor.deploy_accounts(update_template)?;
Ok(())
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
8 changes: 4 additions & 4 deletions tests/common/constants.rs → tests/starknet/constants.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#[allow(dead_code)]
pub const COMPILED_ACCOUNT_CONTRACT_V2: &str =
include_str!("../clob/compiled_account_contract_v2.txt");
include_str!("./clob/compiled_account_contract_v2.txt");
#[allow(dead_code)]
pub const COMPILED_ACCOUNT_CONTRACT_V3: &str =
include_str!("../clob/compiled_account_contract_v3.txt");
include_str!("./clob/compiled_account_contract_v3.txt");
#[allow(dead_code)]
pub const DECLARE_ACCOUNT_V2: &str =
include_str!("../clob/declare_account_v2.txt");
include_str!("./clob/declare_account_v2.txt");
#[allow(dead_code)]
pub const DECLARE_ACCOUNT_V3: &str =
include_str!("../clob/declare_account_v3.txt");
include_str!("./clob/declare_account_v3.txt");

#[allow(dead_code)]
pub const CLASS_HASH: &str =
Expand Down
11 changes: 11 additions & 0 deletions tests/starknet/contract/account/Scarb.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "account"
version = "0.1.0"
cairo-version = "2.5.4"

[dependencies]
starknet = ">=2.5.4"

[[target.starknet-contract]]
sierra = true
casm = true
149 changes: 149 additions & 0 deletions tests/starknet/contract/account/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
use starknet::account::Call;

mod SUPPORTED_TX_VERSION {
const DEPLOY_ACCOUNT: felt252 = 1;
const DECLARE: felt252 = 2;
const INVOKE: felt252 = 1;
}

#[starknet::interface]
trait IAccount<T> {
fn is_valid_signature(self: @T, hash: felt252, signature: Array<felt252>) -> felt252;
fn supports_interface(self: @T, interface_id: felt252) -> bool;
fn public_key(self: @T) -> felt252;
fn id(self: @T) -> u128;
}

#[starknet::contract]
mod Account {
use super::{Call, IAccount, SUPPORTED_TX_VERSION};
use starknet::{get_caller_address, call_contract_syscall, get_tx_info, VALIDATED};
use zeroable::Zeroable;
use array::{ArrayTrait, SpanTrait};
use ecdsa::check_ecdsa_signature;
use box::BoxTrait;

const SIMULATE_TX_VERSION_OFFSET: felt252 = 340282366920938463463374607431768211456; // 2**128
const SRC6_TRAIT_ID: felt252 = 1270010605630597976495846281167968799381097569185364931397797212080166453709; // hash of SNIP-6 trait

#[storage]
struct Storage {
public_key: felt252,
id: u128
}

#[constructor]
fn constructor(ref self: ContractState, public_key: felt252) {
self.public_key.write(public_key);
self.id.write(0);
}

#[abi(embed_v0)]
impl AccountImpl of IAccount<ContractState> {
fn is_valid_signature(self: @ContractState, hash: felt252, signature: Array<felt252>) -> felt252 {
let is_valid = self.is_valid_signature_bool(hash, signature.span());
if is_valid { VALIDATED } else { 0 }
}

fn supports_interface(self: @ContractState, interface_id: felt252) -> bool {
interface_id == SRC6_TRAIT_ID
}

fn public_key(self: @ContractState) -> felt252 {
self.public_key.read()
}

fn id(self: @ContractState) -> u128 {
self.id.read()
}
}

#[abi(per_item)]
#[generate_trait]
impl ProtocolImpl of ProtocolTrait {
fn __execute__(ref self: ContractState, calls: Array<Call>) -> Array<Span<felt252>> {
self.only_protocol();
self.only_supported_tx_version(SUPPORTED_TX_VERSION::INVOKE);
self.execute_multiple_calls(calls)
}

fn __validate__(self: @ContractState, calls: Array<Call>) -> felt252 {
self.only_protocol();
self.only_supported_tx_version(SUPPORTED_TX_VERSION::INVOKE);
self.validate_transaction()
}

fn __validate_declare__(self: @ContractState, class_hash: felt252) -> felt252 {
self.only_protocol();
self.only_supported_tx_version(SUPPORTED_TX_VERSION::DECLARE);
self.validate_transaction()
}

fn __validate_deploy__(self: @ContractState, class_hash: felt252, salt: felt252, public_key: felt252) -> felt252 {
self.only_protocol();
self.only_supported_tx_version(SUPPORTED_TX_VERSION::DEPLOY_ACCOUNT);
self.validate_transaction()
}
}

#[generate_trait]
impl PrivateImpl of PrivateTrait {
fn only_protocol(self: @ContractState) {
let sender = get_caller_address();
assert(sender.is_zero(), 'Account: invalid caller');
}

fn is_valid_signature_bool(self: @ContractState, hash: felt252, signature: Span<felt252>) -> bool {
let is_valid_length = signature.len() == 2_u32;

if !is_valid_length {
return false;
}

check_ecdsa_signature(
hash, self.public_key.read(), *signature.at(0_u32), *signature.at(1_u32)
)
}

fn validate_transaction(self: @ContractState) -> felt252 {
let tx_info = get_tx_info().unbox();
let tx_hash = tx_info.transaction_hash;
let signature = tx_info.signature;

let is_valid = self.is_valid_signature_bool(tx_hash, signature);
assert(is_valid, 'Account: Incorrect tx signature');
VALIDATED
}

fn execute_single_call(self: @ContractState, call: Call) -> Span<felt252> {
let Call{to, selector, calldata} = call;
call_contract_syscall(to, selector, calldata.into()).unwrap()
}

fn execute_multiple_calls(self: @ContractState, mut calls: Array<Call>) -> Array<Span<felt252>> {
let mut res = ArrayTrait::new();
loop {
match calls.pop_front() {
Option::Some(call) => {
let _res = self.execute_single_call(call);
res.append(_res);
},
Option::None(_) => {
break ();
},
};
};
res
}

fn only_supported_tx_version(self: @ContractState, supported_tx_version: felt252) {
let tx_info = get_tx_info().unbox();
let version = tx_info.version;
assert(
version == supported_tx_version ||
version == SIMULATE_TX_VERSION_OFFSET + supported_tx_version,
'Account: Unsupported tx version'
);
}
}
}
Loading

0 comments on commit e44e531

Please sign in to comment.