diff --git a/contracts/Scarb.toml b/contracts/Scarb.toml index b4bedcd..adae74e 100644 --- a/contracts/Scarb.toml +++ b/contracts/Scarb.toml @@ -2,11 +2,16 @@ name = "zkramp" version = "0.1.0" edition = "2023_11" +cairo-version = "2.7.0" +scarb-version = "2.7.0" [dependencies] -starknet = "2.6.4" +starknet = "2.7.0" openzeppelin = { git = "https://github.com/openzeppelin/cairo-contracts", tag = "v0.15.0" } +[dev-dependencies] +cairo_test = "2.7.0" + [tool.fmt] sort-module-level-items = true diff --git a/contracts/src/components/registry.cairo b/contracts/src/components/registry.cairo index 5cd8207..2bb9852 100644 --- a/contracts/src/components/registry.cairo +++ b/contracts/src/components/registry.cairo @@ -1,2 +1,8 @@ pub mod interface; pub mod registry; + +#[cfg(test)] +pub mod registry_mock; + +#[cfg(test)] +pub mod registry_test; diff --git a/contracts/src/components/registry/registry.cairo b/contracts/src/components/registry/registry.cairo index d03d091..6b317f8 100644 --- a/contracts/src/components/registry/registry.cairo +++ b/contracts/src/components/registry/registry.cairo @@ -1,20 +1,32 @@ -#[starknet::interface] -trait IRegisterContract { - fn register_user(ref self: ContractState, revolut_ID: felt252); -} - #[starknet::component] -mod RegistryComponent { - use starknet::storage::Map; +pub mod RegistryComponent { + use core::num::traits::Zero; +use starknet::storage::Map; use starknet::{ContractAddress, get_caller_address}; use zkramp::components::registry::interface::OffchainId; use zkramp::components::registry::interface; + // + // Storage + // + #[storage] struct Storage { Registry_registrations: Map::<(ContractAddress, OffchainId), bool>, } + // + // Errors + // + + pub mod Errors { + pub const ZERO_ADDRESS_CALLER: felt252 = 'Caller is the zero address'; + } + + // + // Registry impl + // + #[embeddable_as(RegistryImpl)] impl Registry< TContractState, +HasComponent, +Drop, @@ -30,6 +42,9 @@ mod RegistryComponent { fn register(ref self: ComponentState, offchain_id: OffchainId) { let caller = get_caller_address(); + // verify caller + assert(caller.is_non_zero(), Errors::ZERO_ADDRESS_CALLER); + // TODO: caller a processor to verify the proof of registration // save registration diff --git a/contracts/src/components/registry/registry_mock.cairo b/contracts/src/components/registry/registry_mock.cairo new file mode 100644 index 0000000..b5beece --- /dev/null +++ b/contracts/src/components/registry/registry_mock.cairo @@ -0,0 +1,51 @@ +use super::registry::RegistryComponent; + +#[starknet::contract] +pub mod RegistryMock { + use starknet::ContractAddress; + use starknet::account::Call; + use zkramp::components::registry::interface::IRegistry; + use zkramp::components::registry::registry::RegistryComponent; + + component!(path: RegistryComponent, storage: registry, event: RegistryEvent); + + // Registry + #[abi(embed_v0)] + impl RegistryImpl = RegistryComponent::RegistryImpl; + + // + // Storage + // + + #[storage] + struct Storage { + #[substorage(v0)] + registry: RegistryComponent::Storage, + } + + // + // Events + // + + #[event] + #[derive(Drop, starknet::Event)] + enum Event { + #[flat] + RegistryEvent: RegistryComponent::Event, + } + + // + // Constructor + // + + #[constructor] + fn constructor(ref self: ContractState) { + // Nothing to be done + } +} + +type ComponentState = RegistryComponent::ComponentState; + +fn COMPONENT() -> ComponentState { + RegistryComponent::component_state_for_testing() +} diff --git a/contracts/src/components/registry/registry_test.cairo b/contracts/src/components/registry/registry_test.cairo new file mode 100644 index 0000000..adfda4d --- /dev/null +++ b/contracts/src/components/registry/registry_test.cairo @@ -0,0 +1,24 @@ +use zkramp::components::registry::interface::{IRegistryDispatcher, IRegistryDispatcherTrait}; +use zkramp::components::registry::registry_mock::RegistryMock; +use zkramp::tests::utils; +use zkramp::tests::constants; + +/// Deploys the registry mock contract. +fn setup_contracts() -> IRegistryDispatcher { + // deploy registry + let registry_contract_address = utils::deploy(RegistryMock::TEST_CLASS_HASH, calldata: array![]); + + IRegistryDispatcher { contract_address: registry_contract_address } +} + +// +// Externals +// + +#[test] +#[should_panic(expected: ('Caller is the zero address', 'ENTRYPOINT_FAILED'))] +fn test_register_from_zero() { + let registry = setup_contracts(); + + registry.register(offchain_id: constants::REVOLUT_ID()); +} diff --git a/contracts/src/lib.cairo b/contracts/src/lib.cairo index 39c289f..c89034e 100644 --- a/contracts/src/lib.cairo +++ b/contracts/src/lib.cairo @@ -1,3 +1,6 @@ pub mod components; pub mod contracts; pub mod utils; + +#[cfg(test)] +pub mod tests; diff --git a/contracts/src/tests.cairo b/contracts/src/tests.cairo new file mode 100644 index 0000000..49f6ff0 --- /dev/null +++ b/contracts/src/tests.cairo @@ -0,0 +1,2 @@ +pub mod constants; +pub mod utils; diff --git a/contracts/src/tests/constants.cairo b/contracts/src/tests/constants.cairo new file mode 100644 index 0000000..af8821f --- /dev/null +++ b/contracts/src/tests/constants.cairo @@ -0,0 +1,9 @@ +use zkramp::components::registry::interface::OffchainId; + +pub fn REVTAG() -> ByteArray { + "my wonderfull, incredible but also very long, revtag" +} + +pub fn REVOLUT_ID() -> OffchainId { + OffchainId::Revolut(REVTAG()) +} diff --git a/contracts/src/tests/utils.cairo b/contracts/src/tests/utils.cairo new file mode 100644 index 0000000..fd8125c --- /dev/null +++ b/contracts/src/tests/utils.cairo @@ -0,0 +1,10 @@ +use starknet::{SyscallResultTrait, syscalls}; + +pub fn deploy(contract_class_hash: felt252, calldata: Array) -> starknet::ContractAddress { + let (address, _) = syscalls::deploy_syscall( + contract_class_hash.try_into().unwrap(), 0, calldata.span(), false + ) + .unwrap_syscall(); + + address +}