From e2d724833bca798f7052fc74c7e98cfc07ee0ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Triay?= Date: Tue, 7 Mar 2023 22:07:00 -0300 Subject: [PATCH 01/15] continue account implementation --- src/openzeppelin/account.cairo | 45 +++++++++++++++++++---- src/openzeppelin/tests/test_account.cairo | 4 +- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/openzeppelin/account.cairo b/src/openzeppelin/account.cairo index e41be2080..a990cf3fb 100644 --- a/src/openzeppelin/account.cairo +++ b/src/openzeppelin/account.cairo @@ -1,11 +1,20 @@ const ACCOUNT_ID: felt = 0x4; +struct AccountCall { + to: felt, + selector: felt, + calldata: Array:: +} + #[account_contract] mod Account { use openzeppelin::account::ACCOUNT_ID; + use openzeppelin::account::AccountCall; use openzeppelin::introspection::erc165::ERC165Contract; + use ecdsa::check_ecdsa_signature; use starknet::get_caller_address; use starknet::get_contract_address; + use starknet::get_tx_info; struct Storage { public_key: felt, @@ -18,9 +27,30 @@ mod Account { } #[external] - fn __execute__(amount: felt) { - let is_valid = is_valid_signature(); - assert(is_valid == true, 'Invalid signature.'); + fn __execute__(calls: Array::) { + let tx_info = unbox(get_tx_info()); + let tx_hash = tx_info.transaction_hash; + let sig = tx_info.signature; + assert(sig.len() == 2_u32, 'bad signature length'); + let is_valid = is_valid_signature(tx_hash, *sig.at(0_u32), *sig.at(1_u32)); + assert(is_valid, 'Invalid signature.'); + + // execute + + // let res: Array::; + // + // for call in calls { + // _res = _call_contract(call); + // res.append(_res); + // } + // + // return res; + } + + fn _call_contract(call: AccountCall) -> felt { + starknet::call_contract_syscall( + call.to, call.selector, call.calldata + ).unwrap_syscall() } #[external] @@ -35,17 +65,18 @@ mod Account { } #[view] - fn is_valid_signature() -> bool { - true + fn is_valid_signature(message: felt, sig_r: felt, sig_s: felt) -> bool { + let _public_key: felt = public_key::read(); + check_ecdsa_signature(message, _public_key, sig_r, sig_s) } fn only_self() { let caller = starknet::get_caller_address(); let self = starknet::get_contract_address(); - assert(1 == 2, 'Account: unauthorized.'); + assert(caller == self, 'Account: unauthorized.'); } - // ERC165Contract + // ERC165 #[view] fn supports_interface(interface_id: felt) -> bool { ERC165Contract::supports_interface(interface_id) diff --git a/src/openzeppelin/tests/test_account.cairo b/src/openzeppelin/tests/test_account.cairo index 7308ec172..ae69920b5 100644 --- a/src/openzeppelin/tests/test_account.cairo +++ b/src/openzeppelin/tests/test_account.cairo @@ -4,7 +4,6 @@ use openzeppelin::introspection::erc165::IERC165_ID; const PUB_KEY: felt = 0x123; - #[test] #[available_gas(2000000)] fn test_erc165() { @@ -15,4 +14,7 @@ fn test_erc165() { let supports_account_interface: bool = Account::supports_interface(ACCOUNT_ID); assert(supports_account_interface, 'Should support account id'); + + let public_key: felt = Account::get_public_key(); + assert(public_key == PUB_KEY, 'Should return pub key'); } From 52019ace0b25ed2383921040f92161e0c2d9807a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Triay?= Date: Tue, 7 Mar 2023 22:29:22 -0300 Subject: [PATCH 02/15] add missing account interface functions --- src/openzeppelin/account.cairo | 65 ++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/src/openzeppelin/account.cairo b/src/openzeppelin/account.cairo index a990cf3fb..3c469f1b6 100644 --- a/src/openzeppelin/account.cairo +++ b/src/openzeppelin/account.cairo @@ -1,7 +1,7 @@ const ACCOUNT_ID: felt = 0x4; struct AccountCall { - to: felt, + to: ContractAddress, selector: felt, calldata: Array:: } @@ -12,6 +12,7 @@ mod Account { use openzeppelin::account::AccountCall; use openzeppelin::introspection::erc165::ERC165Contract; use ecdsa::check_ecdsa_signature; + use starknet::contract_address::contract_address_to_felt; use starknet::get_caller_address; use starknet::get_contract_address; use starknet::get_tx_info; @@ -28,12 +29,7 @@ mod Account { #[external] fn __execute__(calls: Array::) { - let tx_info = unbox(get_tx_info()); - let tx_hash = tx_info.transaction_hash; - let sig = tx_info.signature; - assert(sig.len() == 2_u32, 'bad signature length'); - let is_valid = is_valid_signature(tx_hash, *sig.at(0_u32), *sig.at(1_u32)); - assert(is_valid, 'Invalid signature.'); + assert_valid_transaction(); // execute @@ -47,15 +43,32 @@ mod Account { // return res; } - fn _call_contract(call: AccountCall) -> felt { - starknet::call_contract_syscall( - call.to, call.selector, call.calldata - ).unwrap_syscall() + #[external] + fn __validate__( + contract_address: ContractAddress, + entry_point_selector: felt, + calldata: Array:: + ) { + assert_valid_transaction() + } + + #[external] + fn __validate_declare__(class_hash: felt) { + assert_valid_transaction() + } + + #[external] + fn __validate_deploy__( + class_hash: felt, + contract_address_salt: felt, + _public_key: felt + ) { + assert_valid_transaction() } #[external] fn set_public_key(new_public_key: felt) { - only_self(); + assert_only_self(); public_key::write(new_public_key); } @@ -70,10 +83,12 @@ mod Account { check_ecdsa_signature(message, _public_key, sig_r, sig_s) } - fn only_self() { + fn assert_only_self() { let caller = starknet::get_caller_address(); let self = starknet::get_contract_address(); - assert(caller == self, 'Account: unauthorized.'); + let a = contract_address_to_felt(caller); + let b = contract_address_to_felt(self); + assert(a == b, 'Account: unauthorized.'); } // ERC165 @@ -81,4 +96,26 @@ mod Account { fn supports_interface(interface_id: felt) -> bool { ERC165Contract::supports_interface(interface_id) } + + fn assert_valid_transaction() { + let tx_info = unbox(get_tx_info()); + let tx_hash = tx_info.transaction_hash; + let signature = tx_info.signature; + + assert(signature.len() == 2_u32, 'bad signature length'); + + let is_valid = is_valid_signature( + tx_hash, + *signature.at(0_u32), + *signature.at(1_u32) + ); + + assert(is_valid, 'Invalid signature.'); + } + + fn call_contract(call: AccountCall) -> felt { + starknet::call_contract_syscall( + call.to, call.selector, call.calldata + ).unwrap_syscall() + } } From 50b96bf929609482706cd469cbf5754a4f517c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Triay?= Date: Tue, 7 Mar 2023 22:34:32 -0300 Subject: [PATCH 03/15] tidy up module --- src/openzeppelin/account.cairo | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/openzeppelin/account.cairo b/src/openzeppelin/account.cairo index 3c469f1b6..9a6558610 100644 --- a/src/openzeppelin/account.cairo +++ b/src/openzeppelin/account.cairo @@ -8,15 +8,16 @@ struct AccountCall { #[account_contract] mod Account { - use openzeppelin::account::ACCOUNT_ID; - use openzeppelin::account::AccountCall; - use openzeppelin::introspection::erc165::ERC165Contract; use ecdsa::check_ecdsa_signature; use starknet::contract_address::contract_address_to_felt; use starknet::get_caller_address; use starknet::get_contract_address; use starknet::get_tx_info; + use openzeppelin::account::ACCOUNT_ID; + use openzeppelin::account::AccountCall; + use openzeppelin::introspection::erc165::ERC165Contract; + struct Storage { public_key: felt, } @@ -31,8 +32,6 @@ mod Account { fn __execute__(calls: Array::) { assert_valid_transaction(); - // execute - // let res: Array::; // // for call in calls { @@ -83,6 +82,14 @@ mod Account { check_ecdsa_signature(message, _public_key, sig_r, sig_s) } + // ERC165 + #[view] + fn supports_interface(interface_id: felt) -> bool { + ERC165Contract::supports_interface(interface_id) + } + + // internals + fn assert_only_self() { let caller = starknet::get_caller_address(); let self = starknet::get_contract_address(); @@ -91,12 +98,6 @@ mod Account { assert(a == b, 'Account: unauthorized.'); } - // ERC165 - #[view] - fn supports_interface(interface_id: felt) -> bool { - ERC165Contract::supports_interface(interface_id) - } - fn assert_valid_transaction() { let tx_info = unbox(get_tx_info()); let tx_hash = tx_info.transaction_hash; From aae64518e77accc74739ec7d9c2fe004086bf351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Triay?= Date: Tue, 7 Mar 2023 22:38:34 -0300 Subject: [PATCH 04/15] fix validate --- src/openzeppelin/account.cairo | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/openzeppelin/account.cairo b/src/openzeppelin/account.cairo index 9a6558610..aacd53f5e 100644 --- a/src/openzeppelin/account.cairo +++ b/src/openzeppelin/account.cairo @@ -43,11 +43,7 @@ mod Account { } #[external] - fn __validate__( - contract_address: ContractAddress, - entry_point_selector: felt, - calldata: Array:: - ) { + fn __validate__(calls: Array::) { assert_valid_transaction() } From c485e60425e94354f48ad4065e264890a40d9d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Triay?= Date: Thu, 9 Mar 2023 11:48:49 -0300 Subject: [PATCH 05/15] bump cairo + account changes --- Cargo.lock | 107 ++++++++++++++++++++++++--------- Cargo.toml | 3 +- Makefile | 2 +- src/openzeppelin/account.cairo | 66 ++++++++++++++------ 4 files changed, 128 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e6cd6443e..ce7328ea4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -307,7 +307,7 @@ dependencies = [ [[package]] name = "cairo-lang-casm" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-utils", "env_logger", @@ -323,7 +323,7 @@ dependencies = [ [[package]] name = "cairo-lang-compiler" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "anyhow", "cairo-lang-defs", @@ -347,7 +347,7 @@ dependencies = [ [[package]] name = "cairo-lang-debug" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-proc-macros", "cairo-lang-utils", @@ -358,7 +358,7 @@ dependencies = [ [[package]] name = "cairo-lang-defs" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-debug", "cairo-lang-diagnostics", @@ -379,7 +379,7 @@ dependencies = [ [[package]] name = "cairo-lang-diagnostics" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-filesystem", "cairo-lang-proc-macros", @@ -394,7 +394,7 @@ dependencies = [ [[package]] name = "cairo-lang-eq-solver" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-utils", "env_logger", @@ -408,7 +408,7 @@ dependencies = [ [[package]] name = "cairo-lang-filesystem" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-debug", "cairo-lang-utils", @@ -421,7 +421,7 @@ dependencies = [ [[package]] name = "cairo-lang-formatter" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "anyhow", "cairo-lang-diagnostics", @@ -444,8 +444,9 @@ dependencies = [ [[package]] name = "cairo-lang-language-server" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ + "anyhow", "cairo-lang-compiler", "cairo-lang-debug", "cairo-lang-defs", @@ -460,10 +461,13 @@ dependencies = [ "cairo-lang-starknet", "cairo-lang-syntax", "cairo-lang-utils", + "indoc", + "log", "lsp-types", "salsa", "serde", "serde_json", + "smol_str", "test-log", "tokio", "tower-lsp", @@ -471,7 +475,7 @@ dependencies = [ [[package]] name = "cairo-lang-lowering" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -499,7 +503,7 @@ dependencies = [ [[package]] name = "cairo-lang-parser" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-diagnostics", "cairo-lang-filesystem", @@ -520,7 +524,7 @@ dependencies = [ [[package]] name = "cairo-lang-plugins" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -543,7 +547,7 @@ dependencies = [ [[package]] name = "cairo-lang-proc-macros" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-debug", "quote", @@ -552,7 +556,7 @@ dependencies = [ [[package]] name = "cairo-lang-project" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-filesystem", "indoc", @@ -565,7 +569,7 @@ dependencies = [ [[package]] name = "cairo-lang-runner" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "anyhow", "ark-ff 0.4.0-alpha.7", @@ -593,7 +597,7 @@ dependencies = [ [[package]] name = "cairo-lang-semantic" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "assert_matches", "cairo-lang-debug", @@ -623,7 +627,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "assert_matches", "bimap", @@ -651,7 +655,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-ap-change" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -666,7 +670,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-gas" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -683,7 +687,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-generator" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -714,8 +718,9 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-to-casm" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ + "anyhow", "assert_matches", "cairo-felt", "cairo-lang-casm", @@ -738,7 +743,7 @@ dependencies = [ [[package]] name = "cairo-lang-starknet" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "anyhow", "cairo-lang-compiler", @@ -780,7 +785,7 @@ dependencies = [ [[package]] name = "cairo-lang-syntax" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -794,7 +799,7 @@ dependencies = [ [[package]] name = "cairo-lang-syntax-codegen" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-utils", "env_logger", @@ -806,7 +811,7 @@ dependencies = [ [[package]] name = "cairo-lang-test-runner" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "anyhow", "cairo-felt", @@ -839,7 +844,7 @@ dependencies = [ [[package]] name = "cairo-lang-test-utils" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "cairo-lang-utils", "env_logger", @@ -850,7 +855,7 @@ dependencies = [ [[package]] name = "cairo-lang-utils" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "chrono", "env_logger", @@ -1315,6 +1320,7 @@ checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" dependencies = [ "futures-channel", "futures-core", + "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -1337,6 +1343,17 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +[[package]] +name = "futures-executor" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.25" @@ -1366,6 +1383,12 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + [[package]] name = "futures-util" version = "0.3.25" @@ -2250,6 +2273,32 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rstest" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07f2d176c472198ec1e6551dc7da28f1c089652f66a7b722676c2238ebc0edf" +dependencies = [ + "futures", + "futures-timer", + "rstest_macros", + "rustc_version 0.4.0", +] + +[[package]] +name = "rstest_macros" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7229b505ae0706e64f37ffc54a9c163e11022a6636d58fe1f3f52018257ff9f7" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn", + "unicode-ident", +] + [[package]] name = "rustc-hash" version = "1.1.0" @@ -2665,7 +2714,7 @@ dependencies = [ [[package]] name = "tests" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" dependencies = [ "assert_matches", "cairo-felt", @@ -2674,6 +2723,7 @@ dependencies = [ "cairo-lang-defs", "cairo-lang-diagnostics", "cairo-lang-filesystem", + "cairo-lang-lowering", "cairo-lang-parser", "cairo-lang-plugins", "cairo-lang-runner", @@ -2690,6 +2740,7 @@ dependencies = [ "log", "num-bigint", "pretty_assertions", + "rstest", "salsa", "test-case", "test-log", diff --git a/Cargo.toml b/Cargo.toml index 4294fd6aa..2716fa541 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ members = [ ] [workspace.package] -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" edition = "2021" repository = "https://github.com/starkware-libs/cairo/" license = "Apache-2.0" @@ -72,6 +72,7 @@ pretty_assertions = "1.2.1" proc-macro2 = "1.0" quote = "1.0.21" rayon = "0.9.0" +rstest = "0.16.0" salsa = "0.16.1" serde = { version = "1.0.130", features = ["derive"] } serde_json = "1.0" diff --git a/Makefile b/Makefile index 9ed2f2af3..7969ea043 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ build: cargo build test: - cargo run --bin cairo-test -- --starknet --path src/openzeppelin + cargo run --bin cairo-test -- --starknet --path $(SOURCE_FOLDER) format: cargo run --bin cairo-format -- --recursive $(SOURCE_FOLDER) --print-parsing-errors diff --git a/src/openzeppelin/account.cairo b/src/openzeppelin/account.cairo index aacd53f5e..690766998 100644 --- a/src/openzeppelin/account.cairo +++ b/src/openzeppelin/account.cairo @@ -1,5 +1,8 @@ +use starknet::contract_address::ContractAddressSerde; + const ACCOUNT_ID: felt = 0x4; +#[derive(Drop)] struct AccountCall { to: ContractAddress, selector: felt, @@ -8,8 +11,10 @@ struct AccountCall { #[account_contract] mod Account { + use array::SpanTrait; + use array::ArrayTrait; use ecdsa::check_ecdsa_signature; - use starknet::contract_address::contract_address_to_felt; + use starknet::contract_address::ContractAddressPartialEq; use starknet::get_caller_address; use starknet::get_contract_address; use starknet::get_tx_info; @@ -28,21 +33,29 @@ mod Account { public_key::write(_public_key); } - #[external] - fn __execute__(calls: Array::) { + // to do: serde for AccountCall + // #[external] + fn __execute__(mut calls: Array::) -> Array::> { assert_valid_transaction(); + let mut res = ArrayTrait::new(); + _execute_calls(calls, res) + } - // let res: Array::; - // - // for call in calls { - // _res = _call_contract(call); - // res.append(_res); - // } - // - // return res; + fn _execute_calls(mut calls: Array, mut res: Array::>) -> Array::> { + match calls.pop_front() { + Option::Some(call) => { + let _res = _call_contract(call); + res.append(_res); + return _execute_calls(calls, res); + }, + Option::None(_) => { + return res; + }, + } } - #[external] + // to do: serde for AccountCall + // #[external] fn __validate__(calls: Array::) { assert_valid_transaction() } @@ -78,20 +91,17 @@ mod Account { check_ecdsa_signature(message, _public_key, sig_r, sig_s) } - // ERC165 #[view] fn supports_interface(interface_id: felt) -> bool { ERC165Contract::supports_interface(interface_id) } - // internals + // Internals fn assert_only_self() { - let caller = starknet::get_caller_address(); - let self = starknet::get_contract_address(); - let a = contract_address_to_felt(caller); - let b = contract_address_to_felt(self); - assert(a == b, 'Account: unauthorized.'); + let caller = get_caller_address(); + let self = get_contract_address(); + assert(self == caller, 'Account: unauthorized.'); } fn assert_valid_transaction() { @@ -110,9 +120,25 @@ mod Account { assert(is_valid, 'Invalid signature.'); } - fn call_contract(call: AccountCall) -> felt { + fn _call_contract(call: AccountCall) -> Array:: { starknet::call_contract_syscall( call.to, call.selector, call.calldata ).unwrap_syscall() } } + + +// impl AccountCallSerde of serde::Serde:: { +// fn serialize(ref serialized: Array, input: AccountCall) { +// serde::Serde::serialize(ref serialized, input.to); +// serde::Serde::serialize(ref serialized, input.selector); +// serde::Serde::serialize(ref serialized, input.calldata); +// } +// fn deserialize(ref serialized: Span) -> Option { +// AccountCall { +// to: serde::Serde::::deserialize(ref serialized)?, +// selector: serde::Serde::deserialize(ref serialized)?, +// calldata: serde::Serde::>::deserialize(ref serialized)?, +// } +// } +// } \ No newline at end of file From 921e61fbf2e932970279fc20c1fe29b51ed77053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Triay?= Date: Wed, 15 Mar 2023 19:58:20 -0300 Subject: [PATCH 06/15] fix __execute__, add serde, rename felt>felt252 --- cairo | 2 +- src/openzeppelin/account.cairo | 151 ++++++---- src/openzeppelin/account/old/Account.cairo | 147 ---------- .../account/old/AddressRegistry.cairo | 27 -- src/openzeppelin/account/old/EthAccount.cairo | 146 ---------- src/openzeppelin/account/old/IAccount.cairo | 45 --- src/openzeppelin/account/old/library.cairo | 260 ------------------ src/openzeppelin/introspection/erc165.cairo | 18 +- src/openzeppelin/tests/test_account.cairo | 6 +- src/openzeppelin/tests/test_erc165.cairo | 2 +- 10 files changed, 118 insertions(+), 686 deletions(-) delete mode 100644 src/openzeppelin/account/old/Account.cairo delete mode 100644 src/openzeppelin/account/old/AddressRegistry.cairo delete mode 100644 src/openzeppelin/account/old/EthAccount.cairo delete mode 100644 src/openzeppelin/account/old/IAccount.cairo delete mode 100644 src/openzeppelin/account/old/library.cairo diff --git a/cairo b/cairo index 903337885..0cfcf0394 160000 --- a/cairo +++ b/cairo @@ -1 +1 @@ -Subproject commit 903337885fa19e28f59988a4952d670f72b44b34 +Subproject commit 0cfcf0394d0ee35886f34318d1bf859558136c28 diff --git a/src/openzeppelin/account.cairo b/src/openzeppelin/account.cairo index 690766998..f60a7be1f 100644 --- a/src/openzeppelin/account.cairo +++ b/src/openzeppelin/account.cairo @@ -1,13 +1,10 @@ +use serde::Serde; +use starknet::ContractAddress; use starknet::contract_address::ContractAddressSerde; +use array::ArrayTrait; +use array::SpanTrait; -const ACCOUNT_ID: felt = 0x4; - -#[derive(Drop)] -struct AccountCall { - to: ContractAddress, - selector: felt, - calldata: Array:: -} +const ACCOUNT_ID: felt252 = 0x4; #[account_contract] mod Account { @@ -19,32 +16,35 @@ mod Account { use starknet::get_contract_address; use starknet::get_tx_info; - use openzeppelin::account::ACCOUNT_ID; - use openzeppelin::account::AccountCall; + use option::OptionTrait; + use super::Call; + use super::ArrayCallSerde; + use super::ArrayCallDrop; + use super::ACCOUNT_ID; + use openzeppelin::introspection::erc165::ERC165Contract; struct Storage { - public_key: felt, + public_key: felt252, } #[constructor] - fn constructor(_public_key: felt) { + fn constructor(_public_key: felt252) { ERC165Contract::register_interface(ACCOUNT_ID); public_key::write(_public_key); } - // to do: serde for AccountCall - // #[external] - fn __execute__(mut calls: Array::) -> Array::> { + #[external] + fn __execute__(mut calls: Array) -> Array> { assert_valid_transaction(); let mut res = ArrayTrait::new(); _execute_calls(calls, res) } - fn _execute_calls(mut calls: Array, mut res: Array::>) -> Array::> { + fn _execute_calls(mut calls: Array, mut res: Array>) -> Array> { match calls.pop_front() { Option::Some(call) => { - let _res = _call_contract(call); + let _res = _execute_single_call(call); res.append(_res); return _execute_calls(calls, res); }, @@ -54,45 +54,49 @@ mod Account { } } - // to do: serde for AccountCall - // #[external] - fn __validate__(calls: Array::) { + fn _execute_single_call(mut call: Call) -> Array { + let Call{to, selector, calldata } = call; + starknet::call_contract_syscall(to, selector, calldata).unwrap_syscall() + } + + #[external] + fn __validate__(mut calls: Array) { assert_valid_transaction() } #[external] - fn __validate_declare__(class_hash: felt) { + fn __validate_declare__(class_hash: felt252) { assert_valid_transaction() } #[external] fn __validate_deploy__( - class_hash: felt, - contract_address_salt: felt, - _public_key: felt + class_hash: felt252, + contract_address_salt: felt252, + _public_key: felt252 ) { assert_valid_transaction() } #[external] - fn set_public_key(new_public_key: felt) { + fn set_public_key(new_public_key: felt252) { assert_only_self(); public_key::write(new_public_key); } #[view] - fn get_public_key() -> felt { + fn get_public_key() -> felt252 { public_key::read() } #[view] - fn is_valid_signature(message: felt, sig_r: felt, sig_s: felt) -> bool { - let _public_key: felt = public_key::read(); + fn is_valid_signature(message: felt252, sig_r: felt252, sig_s: felt252) -> bool { + let _public_key: felt252 = public_key::read(); check_ecdsa_signature(message, _public_key, sig_r, sig_s) } #[view] - fn supports_interface(interface_id: felt) -> bool { + fn supports_interface(interface_id: felt252) -> bool { ERC165Contract::supports_interface(interface_id) } @@ -119,26 +123,79 @@ mod Account { assert(is_valid, 'Invalid signature.'); } +} + +struct Call { + to: ContractAddress, + selector: felt252, + calldata: Array +} + +impl ArrayCallDrop of Drop::>; + +impl CallSerde of Serde:: { + fn serialize(ref output: Array, input: Call) { + let Call{to, selector, calldata } = input; + Serde::serialize(ref output, to); + Serde::serialize(ref output, selector); + Serde::serialize(ref output, calldata); + } + + fn deserialize(ref serialized: Span) -> Option { + let to = Serde::::deserialize(ref serialized)?; + let selector = Serde::::deserialize(ref serialized)?; + let calldata = Serde::>::deserialize(ref serialized)?; + Option::Some(Call { to, selector, calldata }) + } +} + +impl ArrayCallSerde of Serde::> { + fn serialize(ref output: Array, mut input: Array) { + Serde::::serialize(ref output, input.len()); + serialize_array_call_helper(ref output, input); + } + + fn deserialize(ref serialized: Span) -> Option> { + let length = *serialized.pop_front()?; + let mut arr = ArrayTrait::new(); + deserialize_array_call_helper(ref serialized, arr, length) + } +} - fn _call_contract(call: AccountCall) -> Array:: { - starknet::call_contract_syscall( - call.to, call.selector, call.calldata - ).unwrap_syscall() +fn serialize_array_call_helper(ref output: Array, mut input: Array) { + match gas::get_gas() { + Option::Some(_) => {}, + Option::None(_) => { + let mut data = ArrayTrait::new(); + data.append('Out of gas'); + panic(data); + }, + } + match input.pop_front() { + Option::Some(value) => { + Serde::::serialize(ref output, value); + serialize_array_call_helper(ref output, input); + }, + Option::None(_) => {}, } } +fn deserialize_array_call_helper( + ref serialized: Span, mut curr_output: Array, remaining: felt252 +) -> Option> { + if remaining == 0 { + return Option::Some(curr_output); + } -// impl AccountCallSerde of serde::Serde:: { -// fn serialize(ref serialized: Array, input: AccountCall) { -// serde::Serde::serialize(ref serialized, input.to); -// serde::Serde::serialize(ref serialized, input.selector); -// serde::Serde::serialize(ref serialized, input.calldata); -// } -// fn deserialize(ref serialized: Span) -> Option { -// AccountCall { -// to: serde::Serde::::deserialize(ref serialized)?, -// selector: serde::Serde::deserialize(ref serialized)?, -// calldata: serde::Serde::>::deserialize(ref serialized)?, -// } -// } -// } \ No newline at end of file + match gas::get_gas() { + Option::Some(_) => {}, + Option::None(_) => { + let mut data = ArrayTrait::new(); + data.append('Out of gas'); + panic(data); + }, + } + + curr_output.append(Serde::::deserialize(ref serialized)?); + deserialize_array_call_helper(ref serialized, curr_output, remaining - 1) +} diff --git a/src/openzeppelin/account/old/Account.cairo b/src/openzeppelin/account/old/Account.cairo deleted file mode 100644 index 23c10199b..000000000 --- a/src/openzeppelin/account/old/Account.cairo +++ /dev/null @@ -1,147 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.6.1 (account/presets/Account.cairo) - -%lang starknet - -from starkware.cairo.common.cairo_builtins import HashBuiltin, SignatureBuiltin, BitwiseBuiltin -from starkware.starknet.common.syscalls import get_tx_info - -from openzeppelin.account.library import Account, AccountCallArray - - -// -// Constructor -// - -@constructor -func constructor{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - range_check_ptr -}(publicKey: felt) { - Account.initializer(publicKey); - return (); -} - -// -// Getters -// - -@view -func getPublicKey{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - range_check_ptr -} () -> (publicKey: felt) { - let (publicKey: felt) = Account.get_public_key(); - return (publicKey=publicKey); -} - -@view -func supportsInterface{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - range_check_ptr -} (interfaceId: felt) -> (success: felt) { - return Account.supports_interface(interfaceId); -} - -// -// Setters -// - -@external -func setPublicKey{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - range_check_ptr -} (newPublicKey: felt) { - Account.set_public_key(newPublicKey); - return (); -} - -// -// Business logic -// - -@view -func isValidSignature{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - ecdsa_ptr: SignatureBuiltin*, - range_check_ptr -}( - hash: felt, - signature_len: felt, - signature: felt* -) -> (isValid: felt) { - let (isValid: felt) = Account.is_valid_signature(hash, signature_len, signature); - return (isValid=isValid); -} - -@external -func __validate__{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - ecdsa_ptr: SignatureBuiltin*, - range_check_ptr -}( - call_array_len: felt, - call_array: AccountCallArray*, - calldata_len: felt, - calldata: felt* -) { - let (tx_info) = get_tx_info(); - Account.is_valid_signature(tx_info.transaction_hash, tx_info.signature_len, tx_info.signature); - return (); -} - -@external -func __validate_declare__{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - ecdsa_ptr: SignatureBuiltin*, - range_check_ptr -} (class_hash: felt) { - let (tx_info) = get_tx_info(); - Account.is_valid_signature(tx_info.transaction_hash, tx_info.signature_len, tx_info.signature); - return (); -} - -@external -func __validate_deploy__{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - ecdsa_ptr: SignatureBuiltin*, - range_check_ptr -} ( - class_hash: felt, - salt: felt, - publicKey: felt -) { - let (tx_info) = get_tx_info(); - Account.is_valid_signature(tx_info.transaction_hash, tx_info.signature_len, tx_info.signature); - return (); -} - -@external -func __execute__{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - ecdsa_ptr: SignatureBuiltin*, - bitwise_ptr: BitwiseBuiltin*, - range_check_ptr, -}( - call_array_len: felt, - call_array: AccountCallArray*, - calldata_len: felt, - calldata: felt* -) -> ( - response_len: felt, - response: felt* -) { - let (response_len, response) = Account.execute( - call_array_len, call_array, calldata_len, calldata - ); - return (response_len, response); -} diff --git a/src/openzeppelin/account/old/AddressRegistry.cairo b/src/openzeppelin/account/old/AddressRegistry.cairo deleted file mode 100644 index 7076bd25a..000000000 --- a/src/openzeppelin/account/old/AddressRegistry.cairo +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.6.1 (account/presets/AddressRegistry.cairo) - -%lang starknet - -from starkware.cairo.common.cairo_builtins import HashBuiltin -from starkware.starknet.common.syscalls import get_caller_address - -@storage_var -func L1_address(L2_address: felt) -> (address: felt) { -} - -@external -func get_L1_address{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - L2_address: felt -) -> (address: felt) { - return L1_address.read(L2_address); -} - -@external -func set_L1_address{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - new_L1_address: felt -) { - let (caller) = get_caller_address(); - L1_address.write(caller, new_L1_address); - return (); -} diff --git a/src/openzeppelin/account/old/EthAccount.cairo b/src/openzeppelin/account/old/EthAccount.cairo deleted file mode 100644 index 50277380d..000000000 --- a/src/openzeppelin/account/old/EthAccount.cairo +++ /dev/null @@ -1,146 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.6.1 (account/presets/EthAccount.cairo) - -%lang starknet -from starkware.cairo.common.cairo_builtins import HashBuiltin, SignatureBuiltin, BitwiseBuiltin -from starkware.starknet.common.syscalls import get_tx_info - -from openzeppelin.account.library import Account, AccountCallArray - -// -// Constructor -// - -@constructor -func constructor{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - range_check_ptr -}(ethAddress: felt) { - Account.initializer(ethAddress); - return (); -} - -// -// Getters -// - -@view -func getEthAddress{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - range_check_ptr -} () -> (ethAddress: felt) { - let (ethAddress: felt) = Account.get_public_key(); - return (ethAddress=ethAddress); -} - -@view -func supportsInterface{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - range_check_ptr -} (interfaceId: felt) -> (success: felt) { - return Account.supports_interface(interfaceId); -} - -// -// Setters -// - -@external -func setEthAddress{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - range_check_ptr -} (newEthAddress: felt) { - Account.set_public_key(newEthAddress); - return (); -} - -// -// Business logic -// - -@view -func isValidSignature{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - bitwise_ptr: BitwiseBuiltin*, - range_check_ptr, -}( - hash: felt, - signature_len: felt, - signature: felt* -) -> (isValid: felt) { - let (isValid) = Account.is_valid_eth_signature(hash, signature_len, signature); - return (isValid=isValid); -} - -@external -func __validate__{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - bitwise_ptr: BitwiseBuiltin*, - range_check_ptr, -}( - call_array_len: felt, - call_array: AccountCallArray*, - calldata_len: felt, - calldata: felt* -) { - let (tx_info) = get_tx_info(); - Account.is_valid_eth_signature(tx_info.transaction_hash, tx_info.signature_len, tx_info.signature); - return (); -} - -@external -func __validate_declare__{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - bitwise_ptr: BitwiseBuiltin*, - range_check_ptr, -} (class_hash: felt) { - let (tx_info) = get_tx_info(); - Account.is_valid_eth_signature(tx_info.transaction_hash, tx_info.signature_len, tx_info.signature); - return (); -} - - -@external -func __validate_deploy__{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - bitwise_ptr: BitwiseBuiltin*, - range_check_ptr -} ( - class_hash: felt, - salt: felt, - ethAddress: felt -) { - let (tx_info) = get_tx_info(); - Account.is_valid_eth_signature(tx_info.transaction_hash, tx_info.signature_len, tx_info.signature); - return (); -} - -@external -func __execute__{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - ecdsa_ptr: SignatureBuiltin*, - bitwise_ptr: BitwiseBuiltin*, - range_check_ptr, -}( - call_array_len: felt, - call_array: AccountCallArray*, - calldata_len: felt, - calldata: felt* -) -> ( - response_len: felt, - response: felt* -) { - let (response_len, response) = Account.execute( - call_array_len, call_array, calldata_len, calldata - ); - return (response_len, response); -} diff --git a/src/openzeppelin/account/old/IAccount.cairo b/src/openzeppelin/account/old/IAccount.cairo deleted file mode 100644 index 8a22d38c1..000000000 --- a/src/openzeppelin/account/old/IAccount.cairo +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.6.1 (account/IAccount.cairo) - -%lang starknet - -from openzeppelin.account.library import AccountCallArray - -@contract_interface -namespace IAccount { - func isValidSignature( - hash: felt, - signature_len: felt, - signature: felt* - ) -> (isValid: felt) { - } - - func __validate__( - call_array_len: felt, - call_array: AccountCallArray*, - calldata_len: felt, - calldata: felt* - ) { - } - - // Parameter temporarily named `cls_hash` instead of `class_hash` (expected). - // See https://github.com/starkware-libs/cairo-lang/issues/100 for details. - func __validate_declare__(cls_hash: felt) { - } - - func __execute__( - call_array_len: felt, - call_array: AccountCallArray*, - calldata_len: felt, - calldata: felt* - ) -> ( - response_len: felt, - response: felt* - ) { - } - - // ERC165 - - func supportsInterface(interfaceId: felt) -> (success: felt) { - } -} diff --git a/src/openzeppelin/account/old/library.cairo b/src/openzeppelin/account/old/library.cairo deleted file mode 100644 index 6723032eb..000000000 --- a/src/openzeppelin/account/old/library.cairo +++ /dev/null @@ -1,260 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts for Cairo v0.6.1 (account/library.cairo) - -%lang starknet - -from starkware.cairo.common.registers import get_fp_and_pc -from starkware.cairo.common.signature import verify_ecdsa_signature -from starkware.cairo.common.cairo_builtins import HashBuiltin, SignatureBuiltin, BitwiseBuiltin -from starkware.cairo.common.alloc import alloc -from starkware.cairo.common.uint256 import Uint256 -from starkware.cairo.common.memcpy import memcpy -from starkware.cairo.common.math import split_felt -from starkware.cairo.common.math_cmp import is_le_felt -from starkware.cairo.common.bool import TRUE, FALSE -from starkware.starknet.common.syscalls import ( - call_contract, - get_caller_address, - get_contract_address, - get_tx_info -) -from starkware.cairo.common.cairo_secp.signature import ( - finalize_keccak, - verify_eth_signature_uint256 -) -from openzeppelin.utils.constants.library import ( - IACCOUNT_ID, - IERC165_ID, - TRANSACTION_VERSION -) - -// -// Storage -// - -@storage_var -func Account_public_key() -> (public_key: felt) { -} - -// -// Structs -// - -struct Call { - to: felt, - selector: felt, - calldata_len: felt, - calldata: felt*, -} - -// Tmp struct introduced while we wait for Cairo -// to support passing `[AccountCall]` to __execute__ -struct AccountCallArray { - to: felt, - selector: felt, - data_offset: felt, - data_len: felt, -} - -namespace Account { - // - // Initializer - // - - func initializer{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - _public_key: felt - ) { - Account_public_key.write(_public_key); - return (); - } - - // - // Guards - // - - func assert_only_self{syscall_ptr: felt*}() { - let (self) = get_contract_address(); - let (caller) = get_caller_address(); - with_attr error_message("Account: caller is not this account") { - assert self = caller; - } - return (); - } - - // - // Getters - // - - func get_public_key{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( - public_key: felt - ) { - return Account_public_key.read(); - } - - func supports_interface{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(interface_id: felt) -> ( - success: felt - ) { - if (interface_id == IERC165_ID) { - return (success=TRUE); - } - if (interface_id == IACCOUNT_ID) { - return (success=TRUE); - } - return (success=FALSE); - } - - // - // Setters - // - - func set_public_key{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}( - new_public_key: felt - ) { - assert_only_self(); - Account_public_key.write(new_public_key); - return (); - } - - // - // Business logic - // - - func is_valid_signature{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - ecdsa_ptr: SignatureBuiltin*, - range_check_ptr, - }(hash: felt, signature_len: felt, signature: felt*) -> (is_valid: felt) { - let (_public_key) = Account_public_key.read(); - - // This interface expects a signature pointer and length to make - // no assumption about signature validation schemes. - // But this implementation does, and it expects a (sig_r, sig_s) pair. - let sig_r = signature[0]; - let sig_s = signature[1]; - - verify_ecdsa_signature( - message=hash, public_key=_public_key, signature_r=sig_r, signature_s=sig_s - ); - - return (is_valid=TRUE); - } - - func is_valid_eth_signature{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - bitwise_ptr: BitwiseBuiltin*, - range_check_ptr, - }(hash: felt, signature_len: felt, signature: felt*) -> (is_valid: felt) { - alloc_locals; - let (_public_key) = get_public_key(); - let (__fp__, _) = get_fp_and_pc(); - - // This interface expects a signature pointer and length to make - // no assumption about signature validation schemes. - // But this implementation does, and it expects a the sig_v, sig_r, - // sig_s, and hash elements. - let sig_v: felt = signature[0]; - let sig_r: Uint256 = Uint256(low=signature[1], high=signature[2]); - let sig_s: Uint256 = Uint256(low=signature[3], high=signature[4]); - let (high, low) = split_felt(hash); - let msg_hash: Uint256 = Uint256(low=low, high=high); - - let (keccak_ptr: felt*) = alloc(); - local keccak_ptr_start: felt* = keccak_ptr; - - with keccak_ptr { - verify_eth_signature_uint256( - msg_hash=msg_hash, r=sig_r, s=sig_s, v=sig_v, eth_address=_public_key - ); - } - // Required to ensure sequencers cannot spoof validation check. - finalize_keccak(keccak_ptr_start=keccak_ptr_start, keccak_ptr_end=keccak_ptr); - - return (is_valid=TRUE); - } - - func execute{ - syscall_ptr: felt*, - pedersen_ptr: HashBuiltin*, - ecdsa_ptr: SignatureBuiltin*, - bitwise_ptr: BitwiseBuiltin*, - range_check_ptr, - }(call_array_len: felt, call_array: AccountCallArray*, calldata_len: felt, calldata: felt*) -> ( - response_len: felt, response: felt* - ) { - alloc_locals; - - let (tx_info) = get_tx_info(); - // Disallow deprecated tx versions - with_attr error_message("Account: deprecated tx version") { - assert is_le_felt(TRANSACTION_VERSION, tx_info.version) = TRUE; - } - - // Assert not a reentrant call - let (caller) = get_caller_address(); - with_attr error_message("Account: reentrant call") { - assert caller = 0; - } - - // TMP: Convert `AccountCallArray` to 'Call'. - let (calls: Call*) = alloc(); - _from_call_array_to_call(call_array_len, call_array, calldata, calls); - let calls_len = call_array_len; - - // Execute call - let (response: felt*) = alloc(); - let (response_len) = _execute_list(calls_len, calls, response); - - return (response_len=response_len, response=response); - } - - func _execute_list{syscall_ptr: felt*}(calls_len: felt, calls: Call*, response: felt*) -> ( - response_len: felt - ) { - alloc_locals; - - // if no more calls - if (calls_len == 0) { - return (response_len=0); - } - - // do the current call - let this_call: Call = [calls]; - let res = call_contract( - contract_address=this_call.to, - function_selector=this_call.selector, - calldata_size=this_call.calldata_len, - calldata=this_call.calldata, - ); - // copy the result in response - memcpy(response, res.retdata, res.retdata_size); - // do the next calls recursively - let (response_len) = _execute_list( - calls_len - 1, calls + Call.SIZE, response + res.retdata_size - ); - return (response_len=response_len + res.retdata_size); - } - - func _from_call_array_to_call{syscall_ptr: felt*}( - call_array_len: felt, call_array: AccountCallArray*, calldata: felt*, calls: Call* - ) { - // if no more calls - if (call_array_len == 0) { - return (); - } - - // parse the current call - assert [calls] = Call( - to=[call_array].to, - selector=[call_array].selector, - calldata_len=[call_array].data_len, - calldata=calldata + [call_array].data_offset - ); - // parse the remaining calls recursively - _from_call_array_to_call( - call_array_len - 1, call_array + AccountCallArray.SIZE, calldata, calls + Call.SIZE - ); - return (); - } -} diff --git a/src/openzeppelin/introspection/erc165.cairo b/src/openzeppelin/introspection/erc165.cairo index 533593512..30a977719 100644 --- a/src/openzeppelin/introspection/erc165.cairo +++ b/src/openzeppelin/introspection/erc165.cairo @@ -1,9 +1,9 @@ -const IERC165_ID: felt = 0x01ffc9a7; -const INVALID_ID: felt = 0xffffffff; +const IERC165_ID: felt252 = 0x01ffc9a7; +const INVALID_ID: felt252 = 0xffffffff; trait IERC165 { - fn supports_interface(interface_id: felt) -> bool; - fn register_interface(interface_id: felt); + fn supports_interface(interface_id: felt252) -> bool; + fn register_interface(interface_id: felt252); } #[contract] @@ -11,30 +11,30 @@ mod ERC165Contract { use openzeppelin::introspection::erc165; struct Storage { - supported_interfaces: LegacyMap::, + supported_interfaces: LegacyMap::, } impl ERC165 of erc165::IERC165 { - fn supports_interface(interface_id: felt) -> bool { + fn supports_interface(interface_id: felt252) -> bool { if interface_id == erc165::IERC165_ID { return true; } supported_interfaces::read(interface_id) } - fn register_interface(interface_id: felt) { + fn register_interface(interface_id: felt252) { assert(interface_id != erc165::INVALID_ID, 'Invalid id'); supported_interfaces::write(interface_id, true); } } #[view] - fn supports_interface(interface_id: felt) -> bool { + fn supports_interface(interface_id: felt252) -> bool { ERC165::supports_interface(interface_id) } #[external] - fn register_interface(interface_id: felt) { + fn register_interface(interface_id: felt252) { ERC165::register_interface(interface_id) } } diff --git a/src/openzeppelin/tests/test_account.cairo b/src/openzeppelin/tests/test_account.cairo index ae69920b5..c3076f1a4 100644 --- a/src/openzeppelin/tests/test_account.cairo +++ b/src/openzeppelin/tests/test_account.cairo @@ -2,11 +2,11 @@ use openzeppelin::account::Account; use openzeppelin::account::ACCOUNT_ID; use openzeppelin::introspection::erc165::IERC165_ID; -const PUB_KEY: felt = 0x123; +const PUB_KEY: felt252 = 0x123; #[test] #[available_gas(2000000)] -fn test_erc165() { +fn test_constructor() { Account::constructor(PUB_KEY); let supports_default_interface: bool = Account::supports_interface(IERC165_ID); @@ -15,6 +15,6 @@ fn test_erc165() { let supports_account_interface: bool = Account::supports_interface(ACCOUNT_ID); assert(supports_account_interface, 'Should support account id'); - let public_key: felt = Account::get_public_key(); + let public_key: felt252 = Account::get_public_key(); assert(public_key == PUB_KEY, 'Should return pub key'); } diff --git a/src/openzeppelin/tests/test_erc165.cairo b/src/openzeppelin/tests/test_erc165.cairo index a387dbfc3..f1ea3482a 100644 --- a/src/openzeppelin/tests/test_erc165.cairo +++ b/src/openzeppelin/tests/test_erc165.cairo @@ -2,7 +2,7 @@ use openzeppelin::introspection::erc165::ERC165Contract; use openzeppelin::introspection::erc165::IERC165_ID; use openzeppelin::introspection::erc165::INVALID_ID; -const OTHER_ID: felt = 0x12345678; +const OTHER_ID: felt252 = 0x12345678; #[test] From fc2d995f4e1e10a9cb6706850ee5ebe71137673f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Triay?= Date: Wed, 15 Mar 2023 20:07:53 -0300 Subject: [PATCH 07/15] tidy up code --- src/openzeppelin/account.cairo | 65 +++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/src/openzeppelin/account.cairo b/src/openzeppelin/account.cairo index f60a7be1f..b5d77e2ce 100644 --- a/src/openzeppelin/account.cairo +++ b/src/openzeppelin/account.cairo @@ -4,8 +4,15 @@ use starknet::contract_address::ContractAddressSerde; use array::ArrayTrait; use array::SpanTrait; +// to do: update ID const ACCOUNT_ID: felt252 = 0x4; +struct Call { + to: ContractAddress, + selector: felt252, + calldata: Array +} + #[account_contract] mod Account { use array::SpanTrait; @@ -24,6 +31,10 @@ mod Account { use openzeppelin::introspection::erc165::ERC165Contract; + // + // Storage and Constructor + // + struct Storage { public_key: felt252, } @@ -34,6 +45,10 @@ mod Account { public_key::write(_public_key); } + // + // Externals + // + #[external] fn __execute__(mut calls: Array) -> Array> { assert_valid_transaction(); @@ -41,24 +56,6 @@ mod Account { _execute_calls(calls, res) } - fn _execute_calls(mut calls: Array, mut res: Array>) -> Array> { - match calls.pop_front() { - Option::Some(call) => { - let _res = _execute_single_call(call); - res.append(_res); - return _execute_calls(calls, res); - }, - Option::None(_) => { - return res; - }, - } - } - - fn _execute_single_call(mut call: Call) -> Array { - let Call{to, selector, calldata } = call; - starknet::call_contract_syscall(to, selector, calldata).unwrap_syscall() - } - #[external] fn __validate__(mut calls: Array) { assert_valid_transaction() @@ -84,6 +81,10 @@ mod Account { public_key::write(new_public_key); } + // + // View + // + #[view] fn get_public_key() -> felt252 { public_key::read() @@ -93,6 +94,8 @@ mod Account { fn is_valid_signature(message: felt252, sig_r: felt252, sig_s: felt252) -> bool { let _public_key: felt252 = public_key::read(); check_ecdsa_signature(message, _public_key, sig_r, sig_s) + // to do: + // return magic value or false } #[view] @@ -100,7 +103,27 @@ mod Account { ERC165Contract::supports_interface(interface_id) } + // // Internals + // + + fn _execute_calls(mut calls: Array, mut res: Array>) -> Array> { + match calls.pop_front() { + Option::Some(call) => { + let _res = _execute_single_call(call); + res.append(_res); + return _execute_calls(calls, res); + }, + Option::None(_) => { + return res; + }, + } + } + + fn _execute_single_call(mut call: Call) -> Array { + let Call{to, selector, calldata } = call; + starknet::call_contract_syscall(to, selector, calldata).unwrap_syscall() + } fn assert_only_self() { let caller = get_caller_address(); @@ -125,12 +148,6 @@ mod Account { } } -struct Call { - to: ContractAddress, - selector: felt252, - calldata: Array -} - impl ArrayCallDrop of Drop::>; impl CallSerde of Serde:: { From 36fdd154bbde59c738b3e985f9942964309a300a Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 24 Mar 2023 15:42:51 -0400 Subject: [PATCH 08/15] update cairo --- cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cairo b/cairo index 0cfcf0394..9c190561c 160000 --- a/cairo +++ b/cairo @@ -1 +1 @@ -Subproject commit 0cfcf0394d0ee35886f34318d1bf859558136c28 +Subproject commit 9c190561ce1e8323665857f1a77082925c817b4c From 9be9ee2b2afa14171134663937e9dfbca3f65239 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 24 Mar 2023 16:03:23 -0400 Subject: [PATCH 09/15] Update Cargo --- Cargo.lock | 278 ++++++++++++++++++++++++++++++++++++++--------------- Cargo.toml | 5 +- 2 files changed, 201 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce7328ea4..2094098a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,7 +71,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" dependencies = [ "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -81,7 +81,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3ba0a3cf584a8ede533a1749b86040e9018cf752265fc39a71c69fe1fafaba5" dependencies = [ "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -93,7 +93,7 @@ dependencies = [ "num-bigint", "num-traits 0.2.15", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -106,7 +106,7 @@ dependencies = [ "num-traits 0.2.15", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -173,7 +173,7 @@ checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -196,7 +196,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -307,7 +307,7 @@ dependencies = [ [[package]] name = "cairo-lang-casm" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-utils", "env_logger", @@ -316,6 +316,7 @@ dependencies = [ "num-bigint", "num-traits 0.2.15", "pretty_assertions", + "serde", "test-case", "test-log", "thiserror", @@ -323,7 +324,7 @@ dependencies = [ [[package]] name = "cairo-lang-compiler" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "anyhow", "cairo-lang-defs", @@ -347,7 +348,7 @@ dependencies = [ [[package]] name = "cairo-lang-debug" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-proc-macros", "cairo-lang-utils", @@ -358,7 +359,7 @@ dependencies = [ [[package]] name = "cairo-lang-defs" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-debug", "cairo-lang-diagnostics", @@ -379,7 +380,7 @@ dependencies = [ [[package]] name = "cairo-lang-diagnostics" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-filesystem", "cairo-lang-proc-macros", @@ -394,7 +395,7 @@ dependencies = [ [[package]] name = "cairo-lang-eq-solver" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-utils", "env_logger", @@ -408,7 +409,7 @@ dependencies = [ [[package]] name = "cairo-lang-filesystem" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-debug", "cairo-lang-utils", @@ -421,7 +422,7 @@ dependencies = [ [[package]] name = "cairo-lang-formatter" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "anyhow", "cairo-lang-diagnostics", @@ -444,7 +445,7 @@ dependencies = [ [[package]] name = "cairo-lang-language-server" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "anyhow", "cairo-lang-compiler", @@ -465,6 +466,7 @@ dependencies = [ "log", "lsp-types", "salsa", + "scarb-metadata", "serde", "serde_json", "smol_str", @@ -475,7 +477,7 @@ dependencies = [ [[package]] name = "cairo-lang-lowering" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -490,6 +492,7 @@ dependencies = [ "cairo-lang-utils", "env_logger", "id-arena", + "indexmap", "indoc", "itertools", "log", @@ -503,7 +506,7 @@ dependencies = [ [[package]] name = "cairo-lang-parser" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-diagnostics", "cairo-lang-filesystem", @@ -524,7 +527,7 @@ dependencies = [ [[package]] name = "cairo-lang-plugins" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -547,16 +550,16 @@ dependencies = [ [[package]] name = "cairo-lang-proc-macros" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-debug", "quote", - "syn", + "syn 1.0.103", ] [[package]] name = "cairo-lang-project" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-filesystem", "indoc", @@ -569,7 +572,7 @@ dependencies = [ [[package]] name = "cairo-lang-runner" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "anyhow", "ark-ff 0.4.0-alpha.7", @@ -597,7 +600,7 @@ dependencies = [ [[package]] name = "cairo-lang-semantic" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "assert_matches", "cairo-lang-debug", @@ -627,7 +630,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "assert_matches", "bimap", @@ -655,7 +658,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-ap-change" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -670,7 +673,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-gas" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-eq-solver", "cairo-lang-sierra", @@ -687,7 +690,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-generator" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-debug", "cairo-lang-defs", @@ -718,7 +721,7 @@ dependencies = [ [[package]] name = "cairo-lang-sierra-to-casm" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "anyhow", "assert_matches", @@ -743,9 +746,10 @@ dependencies = [ [[package]] name = "cairo-lang-starknet" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "anyhow", + "cairo-lang-casm", "cairo-lang-compiler", "cairo-lang-defs", "cairo-lang-diagnostics", @@ -785,7 +789,7 @@ dependencies = [ [[package]] name = "cairo-lang-syntax" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-debug", "cairo-lang-filesystem", @@ -799,7 +803,7 @@ dependencies = [ [[package]] name = "cairo-lang-syntax-codegen" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-utils", "env_logger", @@ -811,7 +815,7 @@ dependencies = [ [[package]] name = "cairo-lang-test-runner" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "anyhow", "cairo-felt", @@ -844,7 +848,7 @@ dependencies = [ [[package]] name = "cairo-lang-test-utils" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "cairo-lang-utils", "env_logger", @@ -855,13 +859,18 @@ dependencies = [ [[package]] name = "cairo-lang-utils" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "chrono", "env_logger", "indexmap", "itertools", "log", + "num-bigint", + "num-integer", + "num-traits 0.2.15", + "serde", + "serde_json", "test-case", "test-log", ] @@ -895,6 +904,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "camino" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +dependencies = [ + "serde", +] + [[package]] name = "cc" version = "1.0.77" @@ -964,7 +982,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -977,7 +995,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -1137,7 +1155,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -1164,7 +1182,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn", + "syn 1.0.103", ] [[package]] @@ -1181,7 +1199,42 @@ checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.103", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.103", ] [[package]] @@ -1205,7 +1258,38 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", +] + +[[package]] +name = "derive_builder" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.103", +] + +[[package]] +name = "derive_builder_macro" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" +dependencies = [ + "derive_builder_core", + "syn 1.0.103", ] [[package]] @@ -1368,7 +1452,7 @@ checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -1426,7 +1510,7 @@ checksum = "40803f2757f84c877f088e62420931f6e05a72514f1f03630384aa30b91d667b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -1572,6 +1656,12 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.3.0" @@ -2081,7 +2171,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -2129,7 +2219,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.103", "version_check", ] @@ -2146,18 +2236,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -2199,9 +2289,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "0.9.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed02d09394c94ffbdfdc755ad62a132e94c3224a8354e78a1200ced34df12edf" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" dependencies = [ "either", "rayon-core", @@ -2209,9 +2299,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -2295,7 +2385,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.0", - "syn", + "syn 1.0.103", "unicode-ident", ] @@ -2320,7 +2410,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.16", + "semver 1.0.17", ] [[package]] @@ -2361,7 +2451,7 @@ dependencies = [ "heck 0.3.3", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -2373,6 +2463,20 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scarb-metadata" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2480a9a896395a1414feebcfe8550b35f4dce0e6a437eeaa0c3d79ec938ddf42" +dependencies = [ + "camino", + "derive_builder", + "semver 1.0.17", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -2396,9 +2500,12 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +dependencies = [ + "serde", +] [[package]] name = "semver-parser" @@ -2411,9 +2518,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.147" +version = "1.0.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9" dependencies = [ "serde_derive", ] @@ -2429,20 +2536,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.3", ] [[package]] name = "serde_json" -version = "1.0.89" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" dependencies = [ "itoa", "ryu", @@ -2457,7 +2564,7 @@ checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -2583,7 +2690,7 @@ checksum = "6569d70430f0f6edc41f6820d00acf63356e6308046ca01e57eeac22ad258c47" dependencies = [ "starknet-curve", "starknet-ff", - "syn", + "syn 1.0.103", ] [[package]] @@ -2647,6 +2754,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8234ae35e70582bfa0f1fedffa6daa248e41dd045310b19800c4a36382c8f60" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "synstructure" version = "0.12.6" @@ -2655,7 +2773,7 @@ checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", "unicode-xid", ] @@ -2698,7 +2816,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -2709,12 +2827,12 @@ checksum = "38f0c854faeb68a048f0f2dc410c5ddae3bf83854ef0e4977d58306a5edef50e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] name = "tests" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" dependencies = [ "assert_matches", "cairo-felt", @@ -2754,22 +2872,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.3", ] [[package]] @@ -2844,7 +2962,7 @@ checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -2921,7 +3039,7 @@ checksum = "7ebd99eec668d0a450c177acbc4d05e0d0d13b1f8d3db13cd706c52cbec4ac04" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -3078,7 +3196,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.103", "wasm-bindgen-shared", ] @@ -3100,7 +3218,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3237,6 +3355,6 @@ checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", "synstructure", ] diff --git a/Cargo.toml b/Cargo.toml index 2716fa541..107fb5d91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ members = [ ] [workspace.package] -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.6" edition = "2021" repository = "https://github.com/starkware-libs/cairo/" license = "Apache-2.0" @@ -71,9 +71,10 @@ path-clean = "0.1.0" pretty_assertions = "1.2.1" proc-macro2 = "1.0" quote = "1.0.21" -rayon = "0.9.0" +rayon = "1.7.0" rstest = "0.16.0" salsa = "0.16.1" +scarb-metadata = "1.0.1" serde = { version = "1.0.130", features = ["derive"] } serde_json = "1.0" sha3 = "0.10.6" From 06ba244947bbec78d9ad58b5a62879332c609182 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 24 Mar 2023 16:04:26 -0400 Subject: [PATCH 10/15] add pausable --- src/openzeppelin/lib.cairo | 1 + src/openzeppelin/security.cairo | 1 + src/openzeppelin/security/pausable.cairo | 39 ++++++++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 src/openzeppelin/security.cairo create mode 100644 src/openzeppelin/security/pausable.cairo diff --git a/src/openzeppelin/lib.cairo b/src/openzeppelin/lib.cairo index 9c80c87ab..a683a7a62 100644 --- a/src/openzeppelin/lib.cairo +++ b/src/openzeppelin/lib.cairo @@ -1,3 +1,4 @@ mod introspection; mod account; +mod security; mod tests; diff --git a/src/openzeppelin/security.cairo b/src/openzeppelin/security.cairo new file mode 100644 index 000000000..bfdf0512a --- /dev/null +++ b/src/openzeppelin/security.cairo @@ -0,0 +1 @@ +mod pausable; diff --git a/src/openzeppelin/security/pausable.cairo b/src/openzeppelin/security/pausable.cairo new file mode 100644 index 000000000..980259e40 --- /dev/null +++ b/src/openzeppelin/security/pausable.cairo @@ -0,0 +1,39 @@ +#[contract] +mod Pausable { + use starknet::ContractAddress; + use starknet::get_caller_address; + + struct Storage { + _paused: bool, + } + + #[event] + fn Paused(account: ContractAddress) {} + + #[event] + fn Unpaused(account: ContractAddress) {} + + fn is_paused() -> bool { + _paused::read() + } + + fn assert_not_paused() { + assert(!is_paused(), 'Pausable: paused'); + } + + fn assert_paused() { + assert(is_paused(), 'Pausable: not paused'); + } + + fn pause() { + assert_not_paused(); + _paused::write(true); + Paused(get_caller_address()); + } + + fn unpause() { + assert_paused(); + _paused::write(false); + Unpaused(get_caller_address()); + } +} \ No newline at end of file From c954a87bc538ff8eb91f08c7d414edc9e1719b74 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 24 Mar 2023 16:04:56 -0400 Subject: [PATCH 11/15] add pausable tests --- src/openzeppelin/tests.cairo | 1 + src/openzeppelin/tests/test_pausable.cairo | 33 ++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/openzeppelin/tests/test_pausable.cairo diff --git a/src/openzeppelin/tests.cairo b/src/openzeppelin/tests.cairo index 4bc4f188e..1fdb841b3 100644 --- a/src/openzeppelin/tests.cairo +++ b/src/openzeppelin/tests.cairo @@ -1,2 +1,3 @@ mod test_erc165; mod test_account; +mod test_pausable; diff --git a/src/openzeppelin/tests/test_pausable.cairo b/src/openzeppelin/tests/test_pausable.cairo new file mode 100644 index 000000000..56d6e5df5 --- /dev/null +++ b/src/openzeppelin/tests/test_pausable.cairo @@ -0,0 +1,33 @@ +use openzeppelin::security::pausable::Pausable; + +#[test] +#[available_gas(2000000)] +fn test_pause_when_unpaused() { + assert(!Pausable::is_paused(),'Should not be paused'); + Pausable::pause(); + assert(Pausable::is_paused(),'Should be paused'); +} + +#[test] +#[available_gas(2000000)] +#[should_panic(expected = ('Pausable: paused', ))] +fn test_pause_when_paused() { + Pausable::pause(); + Pausable::pause(); +} + +#[test] +#[available_gas(2000000)] +fn test_unpause_when_paused() { + Pausable::pause(); + assert(Pausable::is_paused(), 'Should be paused'); + Pausable::unpause(); + assert(!Pausable::is_paused(), 'Should be unpaused'); +} + +#[test] +#[available_gas(2000000)] +#[should_panic(expected = ('Pausable: not paused', ))] +fn test_unpause_when_unpaused() { + Pausable::unpause(); +} From 8b99c62547f2a5a0be5c80004d090483c0afe04f Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 24 Mar 2023 19:49:31 -0400 Subject: [PATCH 12/15] add mock pausable and tests --- src/openzeppelin/lib.cairo | 1 + src/openzeppelin/mocks.cairo | 1 + src/openzeppelin/mocks/mock_pausable.cairo | 37 +++++++++++++++ src/openzeppelin/tests/test_pausable.cairo | 54 ++++++++++++++++++++++ 4 files changed, 93 insertions(+) create mode 100644 src/openzeppelin/mocks.cairo create mode 100644 src/openzeppelin/mocks/mock_pausable.cairo diff --git a/src/openzeppelin/lib.cairo b/src/openzeppelin/lib.cairo index a683a7a62..056e1e7ab 100644 --- a/src/openzeppelin/lib.cairo +++ b/src/openzeppelin/lib.cairo @@ -1,4 +1,5 @@ mod introspection; mod account; mod security; +mod mocks; mod tests; diff --git a/src/openzeppelin/mocks.cairo b/src/openzeppelin/mocks.cairo new file mode 100644 index 000000000..60df001ef --- /dev/null +++ b/src/openzeppelin/mocks.cairo @@ -0,0 +1 @@ +mod mock_pausable; diff --git a/src/openzeppelin/mocks/mock_pausable.cairo b/src/openzeppelin/mocks/mock_pausable.cairo new file mode 100644 index 000000000..e8a27b892 --- /dev/null +++ b/src/openzeppelin/mocks/mock_pausable.cairo @@ -0,0 +1,37 @@ +#[contract] +mod MockPausable { + use openzeppelin::security::pausable::Pausable; + + use starknet::ContractAddress; + use starknet::get_caller_address; + + struct Storage { + _counter: felt252 + } + + #[view] + fn is_paused() -> bool { + Pausable::is_paused() + } + + #[view] + fn get_count() -> felt252 { + _counter::read() + } + + #[external] + fn assert_unpaused_and_increment() { + Pausable::assert_not_paused(); + _counter::write(_counter::read() + 1); + } + + #[external] + fn pause() { + Pausable::pause(); + } + + #[external] + fn unpause() { + Pausable::unpause(); + } +} \ No newline at end of file diff --git a/src/openzeppelin/tests/test_pausable.cairo b/src/openzeppelin/tests/test_pausable.cairo index 56d6e5df5..1442052dd 100644 --- a/src/openzeppelin/tests/test_pausable.cairo +++ b/src/openzeppelin/tests/test_pausable.cairo @@ -1,4 +1,9 @@ use openzeppelin::security::pausable::Pausable; +use openzeppelin::mocks::mock_pausable::MockPausable; + +// +// Library +// #[test] #[available_gas(2000000)] @@ -31,3 +36,52 @@ fn test_unpause_when_paused() { fn test_unpause_when_unpaused() { Pausable::unpause(); } + +// +// Mock Pausable +// + +#[test] +#[available_gas(2000000)] +fn test_mock_pause_when_unpaused() { + assert(MockPausable::is_paused() == false, 'Should not be paused'); + assert(MockPausable::get_count() == 0, 'Should be 0'); + MockPausable::assert_unpaused_and_increment(); + assert(MockPausable::get_count() == 1, 'Should increment'); + MockPausable::pause(); + assert(MockPausable::is_paused() == true, 'Should be paused'); +} + +#[test] +#[available_gas(2000000)] +#[should_panic(expected = ('Pausable: paused', ))] +fn test_mock_pause_when_paused() { + MockPausable::pause(); + MockPausable::pause(); +} + +#[test] +#[available_gas(2000000)] +#[should_panic(expected = ('Pausable: paused', ))] +fn test_mock_pause_assertion() { + MockPausable::pause(); + MockPausable::assert_unpaused_and_increment(); +} + +#[test] +#[available_gas(2000000)] +fn test_mock_unpause_when_paused() { + MockPausable::pause(); + assert(MockPausable::is_paused() == true, 'Should be paused'); + MockPausable::unpause(); + MockPausable::assert_unpaused_and_increment(); + assert(MockPausable::get_count() == 1, 'Should increment'); +} + +#[test] +#[available_gas(2000000)] +#[should_panic(expected = ('Pausable: not paused', ))] +fn test_mock_unpause_when_unpaused() { + assert(MockPausable::is_paused() == false, 'Should be unpaused'); + MockPausable::unpause(); +} From 2fa099578856fafc0cffcdea2a7ecf7fd0608299 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 24 Mar 2023 19:58:17 -0400 Subject: [PATCH 13/15] remove initial tests --- src/openzeppelin/tests/test_pausable.cairo | 49 ++-------------------- 1 file changed, 4 insertions(+), 45 deletions(-) diff --git a/src/openzeppelin/tests/test_pausable.cairo b/src/openzeppelin/tests/test_pausable.cairo index 1442052dd..7649450ab 100644 --- a/src/openzeppelin/tests/test_pausable.cairo +++ b/src/openzeppelin/tests/test_pausable.cairo @@ -1,49 +1,8 @@ -use openzeppelin::security::pausable::Pausable; use openzeppelin::mocks::mock_pausable::MockPausable; -// -// Library -// - #[test] #[available_gas(2000000)] fn test_pause_when_unpaused() { - assert(!Pausable::is_paused(),'Should not be paused'); - Pausable::pause(); - assert(Pausable::is_paused(),'Should be paused'); -} - -#[test] -#[available_gas(2000000)] -#[should_panic(expected = ('Pausable: paused', ))] -fn test_pause_when_paused() { - Pausable::pause(); - Pausable::pause(); -} - -#[test] -#[available_gas(2000000)] -fn test_unpause_when_paused() { - Pausable::pause(); - assert(Pausable::is_paused(), 'Should be paused'); - Pausable::unpause(); - assert(!Pausable::is_paused(), 'Should be unpaused'); -} - -#[test] -#[available_gas(2000000)] -#[should_panic(expected = ('Pausable: not paused', ))] -fn test_unpause_when_unpaused() { - Pausable::unpause(); -} - -// -// Mock Pausable -// - -#[test] -#[available_gas(2000000)] -fn test_mock_pause_when_unpaused() { assert(MockPausable::is_paused() == false, 'Should not be paused'); assert(MockPausable::get_count() == 0, 'Should be 0'); MockPausable::assert_unpaused_and_increment(); @@ -55,7 +14,7 @@ fn test_mock_pause_when_unpaused() { #[test] #[available_gas(2000000)] #[should_panic(expected = ('Pausable: paused', ))] -fn test_mock_pause_when_paused() { +fn test_pause_when_paused() { MockPausable::pause(); MockPausable::pause(); } @@ -63,14 +22,14 @@ fn test_mock_pause_when_paused() { #[test] #[available_gas(2000000)] #[should_panic(expected = ('Pausable: paused', ))] -fn test_mock_pause_assertion() { +fn test_pause_assertion() { MockPausable::pause(); MockPausable::assert_unpaused_and_increment(); } #[test] #[available_gas(2000000)] -fn test_mock_unpause_when_paused() { +fn test_unpause_when_paused() { MockPausable::pause(); assert(MockPausable::is_paused() == true, 'Should be paused'); MockPausable::unpause(); @@ -81,7 +40,7 @@ fn test_mock_unpause_when_paused() { #[test] #[available_gas(2000000)] #[should_panic(expected = ('Pausable: not paused', ))] -fn test_mock_unpause_when_unpaused() { +fn test_unpause_when_unpaused() { assert(MockPausable::is_paused() == false, 'Should be unpaused'); MockPausable::unpause(); } From 6ddd14ec62d0399eb5aea9532b2eae2a713ce5ca Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 24 Mar 2023 20:00:22 -0400 Subject: [PATCH 14/15] add line --- src/openzeppelin/security/pausable.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openzeppelin/security/pausable.cairo b/src/openzeppelin/security/pausable.cairo index 980259e40..ccc85d350 100644 --- a/src/openzeppelin/security/pausable.cairo +++ b/src/openzeppelin/security/pausable.cairo @@ -36,4 +36,4 @@ mod Pausable { _paused::write(false); Unpaused(get_caller_address()); } -} \ No newline at end of file +} From 912d33d80fb22e0d79004ca6c6d893b11da469cc Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 24 Mar 2023 20:01:32 -0400 Subject: [PATCH 15/15] add line --- src/openzeppelin/mocks/mock_pausable.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openzeppelin/mocks/mock_pausable.cairo b/src/openzeppelin/mocks/mock_pausable.cairo index e8a27b892..496e3301b 100644 --- a/src/openzeppelin/mocks/mock_pausable.cairo +++ b/src/openzeppelin/mocks/mock_pausable.cairo @@ -34,4 +34,4 @@ mod MockPausable { fn unpause() { Pausable::unpause(); } -} \ No newline at end of file +}