diff --git a/.github/workflows/starknet-contracts.yml b/.github/workflows/starknet-contracts.yml index a516ba92..3b165a21 100644 --- a/.github/workflows/starknet-contracts.yml +++ b/.github/workflows/starknet-contracts.yml @@ -11,7 +11,7 @@ jobs: - uses: actions/checkout@v3 - uses: software-mansion/setup-scarb@v1 with: - scarb-version: "nightly" + scarb-version: 'nightly' - name: Check cairo format run: scarb fmt --check working-directory: onchain @@ -24,7 +24,8 @@ jobs: - uses: actions/checkout@v3 - uses: software-mansion/setup-scarb@v1 with: - scarb-version: "nightly" + scarb-version: 'nightly' - name: Run cairo tests + uses: foundry-rs/setup-snfoundry@v3 run: scarb test working-directory: onchain diff --git a/onchain/.snfoundry_cache/.prev_tests_failed b/onchain/.snfoundry_cache/.prev_tests_failed new file mode 100644 index 00000000..e69de29b diff --git a/onchain/Scarb.lock b/onchain/Scarb.lock index 9edcf8be..15dca859 100644 --- a/onchain/Scarb.lock +++ b/onchain/Scarb.lock @@ -4,3 +4,11 @@ version = 1 [[package]] name = "joyboy" version = "0.1.0" +dependencies = [ + "snforge_std", +] + +[[package]] +name = "snforge_std" +version = "0.21.0" +source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.21.0#2996b8c1dd66b2715fc67e69578089f278a46790" diff --git a/onchain/Scarb.toml b/onchain/Scarb.toml index 2a838a36..b1e4e32a 100644 --- a/onchain/Scarb.toml +++ b/onchain/Scarb.toml @@ -6,3 +6,16 @@ edition = "2023_11" # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html [dependencies] +starknet = "2.6.3" + +[dev-dependencies] +snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.21.0" } + +#[lib] + +[scripts] +test = "snforge test" + +[[target.starknet-contract]] +casm = true +sierra = true diff --git a/onchain/src/lib.cairo b/onchain/src/lib.cairo index e2d818c5..7e0c8157 100644 --- a/onchain/src/lib.cairo +++ b/onchain/src/lib.cairo @@ -1,4 +1,7 @@ pub mod bech32; pub mod bip340; +pub mod social_account; + pub mod nostr_profile; pub mod social_pay_request; + diff --git a/onchain/src/social_account.cairo b/onchain/src/social_account.cairo new file mode 100644 index 00000000..16181de9 --- /dev/null +++ b/onchain/src/social_account.cairo @@ -0,0 +1,101 @@ +use starknet::{ContractAddress, get_caller_address, get_contract_address, contract_address_const}; + +#[starknet::interface] +pub trait ISocialPayAccount { + fn get_public_key(self: @TContractState) -> u256; +} + + +#[starknet::contract] +pub mod SocialPayAccount { + #[storage] + struct Storage { + #[key] + public_key: u256 + } + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + AccountCreated: AccountCreated, + } + + #[derive(Drop, starknet::Event)] + struct AccountCreated { + #[key] + public_key: u256 + } + + #[constructor] + fn constructor(ref self: ContractState, public_key: u256) { + self.public_key.write(public_key); + self.emit(AccountCreated { public_key: public_key }); + } + + #[abi(embed_v0)] + impl SocialPayAccount of super::ISocialPayAccount { + fn get_public_key(self: @ContractState) -> u256 { + self.public_key.read() + } + } +} + +#[cfg(test)] +mod tests { + use core::traits::Into; + use core::array::ArrayTrait; + use starknet::{ + ContractAddress, get_caller_address, get_contract_address, contract_address_const + }; + use snforge_std as snf; + use snforge_std::{ + declare, ContractClassTrait, start_prank, stop_prank, CheatTarget, spy_events, SpyOn, + EventSpy, EventFetcher, Event, EventAssertions + }; + use super::{ + ISocialPayAccountDispatcher, ISocialPayAccountDispatcherTrait, + ISocialPayAccountSafeDispatcher, ISocialPayAccountSafeDispatcherTrait + }; + + + const public_key: u256 = 45; + + + fn deploy_social_account() -> ContractAddress { + let contract = declare("SocialPayAccount"); + + let mut social_account_calldata = array![]; + public_key.serialize(ref social_account_calldata); + + let address = contract.precalculate_address(@social_account_calldata); + + let mut spy = spy_events(SpyOn::One(address)); + + let deployed_contract_address = contract.deploy(@social_account_calldata).unwrap(); + + spy.fetch_events(); + + assert(spy.events.len() == 1, 'there should be one event'); + + let (_, event) = spy.events.at(0); + assert(event.keys.at(0) == @selector!("AccountCreated"), 'Wrong event name'); + + let event_key = (*event.keys.at(1)).into(); + + assert(event_key == public_key, 'Wrong Public Key'); + + deployed_contract_address + } + + + #[test] + fn test_get_public_key() { + let contract_address = deploy_social_account(); + let dispatcher = ISocialPayAccountDispatcher { contract_address }; + + let get_public_key = dispatcher.get_public_key(); + + assert!(get_public_key == 45, "Public key is not the same"); + } +} +