Skip to content

Commit

Permalink
dev: test setup (#3)
Browse files Browse the repository at this point in the history
* better test compilation + structure

* ci fix
  • Loading branch information
drspacemn authored Sep 16, 2024
1 parent 53604fb commit 639f852
Show file tree
Hide file tree
Showing 20 changed files with 687 additions and 420 deletions.
100 changes: 5 additions & 95 deletions contracts/Scarb.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,110 +5,20 @@ version = 1
name = "kudos"
version = "0.1.0"
dependencies = [
"openzeppelin",
"snforge_std",
]

[[package]]
name = "openzeppelin"
version = "0.16.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb"
dependencies = [
"openzeppelin_access",
"openzeppelin_account",
"openzeppelin_governance",
"openzeppelin_introspection",
"openzeppelin_merkle_tree",
"openzeppelin_presets",
"openzeppelin_security",
"openzeppelin_token",
"openzeppelin_upgrades",
"openzeppelin_utils",
]

[[package]]
name = "openzeppelin_access"
version = "0.16.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb"
dependencies = [
"openzeppelin_introspection",
"openzeppelin_utils",
]

[[package]]
name = "openzeppelin_account"
version = "0.16.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb"
dependencies = [
"openzeppelin_introspection",
"openzeppelin_utils",
]

[[package]]
name = "openzeppelin_governance"
version = "0.16.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb"
dependencies = [
"openzeppelin_access",
"openzeppelin_introspection",
]

[[package]]
name = "openzeppelin_introspection"
version = "0.16.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb"

[[package]]
name = "openzeppelin_merkle_tree"
version = "0.16.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb"

[[package]]
name = "openzeppelin_presets"
version = "0.16.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb"
dependencies = [
"openzeppelin_access",
"openzeppelin_account",
"openzeppelin_introspection",
"openzeppelin_token",
"openzeppelin_upgrades",
]

[[package]]
name = "openzeppelin_security"
version = "0.16.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb"

[[package]]
name = "openzeppelin_token"
version = "0.16.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb"
dependencies = [
"openzeppelin_account",
"openzeppelin_governance",
"openzeppelin_introspection",
]

[[package]]
name = "openzeppelin_upgrades"
version = "0.16.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb"

[[package]]
name = "openzeppelin_utils"
version = "0.16.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.16.0#ba00ce76a93dcf25c081ab2698da20690b5a1cfb"

[[package]]
name = "snforge_scarb_plugin"
version = "0.1.0"
source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.30.0#196f06b251926697c3d66800f2a93ae595e76496"
version = "0.2.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:2e4ce3ebe3f49548bd26908391b5d78537a765d827df0d96c32aeb88941d0d67"

[[package]]
name = "snforge_std"
version = "0.30.0"
source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.30.0#196f06b251926697c3d66800f2a93ae595e76496"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:2f3c4846881813ac0f5d1460981249c9f5e2a6831e752beedf9b70975495b4ec"
dependencies = [
"snforge_scarb_plugin",
]
4 changes: 2 additions & 2 deletions contracts/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ sort-module-level-items = true

[dependencies]
starknet = "2.8.2"
openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.16.0" }

[dev-dependencies]
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.30.0" }
assert_macros = "2.8.2"
snforge_std = "0.30.0"

[[target.starknet-contract]]
54 changes: 2 additions & 52 deletions contracts/src/credential_registry/component.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
pub mod CredentialRegistryComponent {
use core::num::traits::zero::Zero;
use kudos::credential_registry::interface::ICredentialRegistry;
use openzeppelin::account::interface::{AccountABIDispatcherTrait, AccountABIDispatcher};
use starknet::storage::{
StoragePointerReadAccess, StoragePointerWriteAccess, StoragePathEntry, Map
};
Expand All @@ -12,8 +11,6 @@ pub mod CredentialRegistryComponent {
pub struct Storage {
credentials: Map::<felt252, ContractAddress>,
user_to_credentials: Map::<ContractAddress, felt252>,
credentials_w_pin: Map::<felt252, ContractAddress>,
user_to_credentials_w_pin: Map::<ContractAddress, felt252>,
total_credentials: u128,
}

Expand All @@ -28,12 +25,10 @@ pub mod CredentialRegistryComponent {
#[key]
pub address: ContractAddress,
pub hash: felt252,
pub hash_w_pin: felt252
}

pub mod CredentialRegistryErrors {
pub const CREDENTIAL_REGISTERED: felt252 = 'User prev registered cred';
pub const CREDENTIAL_W_PIN_REGISTERED: felt252 = 'User prev registered cred_w_pin';
pub const CREDENTIAL_INVALID: felt252 = 'User provided is invalid';
pub const INVALID_SIGNATURE: felt252 = 'Invalid signature provided';
}
Expand All @@ -43,24 +38,18 @@ pub mod CredentialRegistryComponent {
TContractState, +HasComponent<TContractState>
> of ICredentialRegistry<ComponentState<TContractState>> {
fn register_credentials(
ref self: ComponentState<TContractState>,
hash: felt252,
signature: Array<felt252>,
hash_w_pin: felt252,
signature_w_pin: Array<felt252>
ref self: ComponentState<TContractState>, hash: felt252, signature: Array<felt252>,
) {
assert(hash != hash_w_pin, CredentialRegistryErrors::CREDENTIAL_INVALID);
let address = get_caller_address();

self._register_credentials(hash, address, signature);
self._register_credential_w_pin(hash_w_pin, address, signature_w_pin);

let prev_total = self.total_credentials.read();
self.total_credentials.write(prev_total + 1);

// TODO: mint $KUDOS here

self.emit(CredentialsRegistered { address, hash, hash_w_pin })
self.emit(CredentialsRegistered { address, hash })
}

fn get_credential(
Expand All @@ -75,18 +64,6 @@ pub mod CredentialRegistryComponent {
self.credentials.entry(hash).read()
}

fn get_credential_w_pin(
self: @ComponentState<TContractState>, address: ContractAddress
) -> felt252 {
self.user_to_credentials_w_pin.entry(address).read()
}

fn get_credential_address_w_pin(
self: @ComponentState<TContractState>, hash: felt252
) -> ContractAddress {
self.credentials_w_pin.entry(hash).read()
}

fn get_total_credentials(self: @ComponentState<TContractState>) -> u128 {
self.total_credentials.read()
}
Expand All @@ -111,35 +88,8 @@ pub mod CredentialRegistryComponent {
CredentialRegistryErrors::CREDENTIAL_REGISTERED
);

let account = AccountABIDispatcher { contract_address };
assert(
account.is_valid_signature(hash, signature) == starknet::VALIDATED,
CredentialRegistryErrors::INVALID_SIGNATURE
);

self.credentials.entry(hash).write(contract_address);
self.user_to_credentials.entry(contract_address).write(hash);
}

fn _register_credential_w_pin(
ref self: ComponentState<TContractState>,
hash: felt252,
contract_address: ContractAddress,
signature: Array<felt252>
) {
assert(
self.credentials_w_pin.entry(hash).read() == contract_address_const::<0>(),
CredentialRegistryErrors::CREDENTIAL_W_PIN_REGISTERED
);

let account = AccountABIDispatcher { contract_address };
assert(
account.is_valid_signature(hash, signature) == starknet::VALIDATED,
CredentialRegistryErrors::INVALID_SIGNATURE
);

self.credentials_w_pin.entry(hash).write(contract_address);
self.user_to_credentials_w_pin.entry(contract_address).write(hash);
}
}
}
10 changes: 1 addition & 9 deletions contracts/src/credential_registry/interface.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,9 @@ use starknet::ContractAddress;

#[starknet::interface]
pub trait ICredentialRegistry<TState> {
fn register_credentials(
ref self: TState,
hash: felt252,
signature: Array<felt252>,
hash_w_pin: felt252,
signature_w_pin: Array<felt252>
);
fn register_credentials(ref self: TState, hash: felt252, signature: Array<felt252>,);
fn get_credential(self: @TState, address: ContractAddress) -> felt252;
fn get_credential_address(self: @TState, hash: felt252) -> ContractAddress;
fn get_credential_w_pin(self: @TState, address: ContractAddress) -> felt252;
fn get_credential_address_w_pin(self: @TState, hash: felt252) -> ContractAddress;
fn get_total_credentials(self: @TState) -> u128;
fn is_registered(self: @TState, address: ContractAddress) -> bool;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[starknet::contract]
pub(crate) mod CredentialRegistryMock {
pub mod CredentialRegistryMock {
use kudos::credential_registry::component::CredentialRegistryComponent;

component!(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use kudos::credential_registry::ICredentialRegistry;

use kudos::credential_registry::component::{
CredentialRegistryComponent, CredentialRegistryComponent::InternalImpl
};
use super::mocks::mock_credential_registry::CredentialRegistryMock;

//
// Setup
//

type ComponentState =
CredentialRegistryComponent::ComponentState<CredentialRegistryMock::ContractState>;

impl ComponentStateDefault of Default<ComponentState> {
fn default() -> ComponentState {
CredentialRegistryComponent::component_state_for_testing()
}
}

#[test]
fn test_initial_values() {
let mut registry: ComponentState = Default::default();

assert!(registry.get_total_credentials() == 0);
}
10 changes: 10 additions & 0 deletions contracts/src/interface.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#[starknet::interface]
pub trait IKudos<TState> {
fn give_kudos(
ref self: TState,
amount: felt252,
sender_credentials: felt252,
receiver_credentials: felt252,
description: felt252,
);
}
51 changes: 28 additions & 23 deletions contracts/src/kudos.cairo
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
#[starknet::contract]
pub mod Kudos {
use openzeppelin::access::ownable::OwnableComponent;
use openzeppelin::token::erc20::{ERC20Component, ERC20HooksEmptyImpl};
// use kudos::token::{IERC20, IERC20Metadata};
use kudos::IKudos;
use kudos::oz16::erc20::{ERC20Component, ERC20HooksEmptyImpl};
use kudos::oz16::ownable::OwnableComponent;
use starknet::ContractAddress;

component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
component!(path: ERC20Component, storage: erc20, event: ERC20Event);

// Ownable Mixin
#[abi(embed_v0)]
impl OwnableMixinImpl = OwnableComponent::OwnableMixinImpl<ContractState>;
impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;
impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;

// ERC20 Mixin
#[abi(embed_v0)]
impl ERC20MixinImpl = ERC20Component::ERC20MixinImpl<ContractState>;
impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;
impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;
impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;

// TODO: Embed the credential registry component

#[storage]
struct Storage {
#[substorage(v0)]
ownable: OwnableComponent::Storage,
#[substorage(v0)]
erc20: ERC20Component::Storage,
#[substorage(v0)]
ownable: OwnableComponent::Storage,
}

// TODO: define contract errors
Expand All @@ -35,27 +35,32 @@ pub mod Kudos {
#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
OwnableEvent: OwnableComponent::Event,
#[flat]
ERC20Event: ERC20Component::Event,
#[flat]
OwnableEvent: OwnableComponent::Event,
}

#[constructor]
fn constructor(
ref self: ContractState,
name: ByteArray,
symbol: ByteArray,
initial_supply: u256,
recipient: ContractAddress,
owner: ContractAddress
ref self: ContractState, name: ByteArray, symbol: ByteArray, owner: ContractAddress
) {
self.ownable.initializer(owner);
self.erc20.initializer(name, symbol);
self.ownable.initializer(owner);
}
// TODO:
// - define and implement IKudos interface including `give_kudos`
// - allow the credential registry to `mint` to a recipient
// - don't expose `transfer` only `transfer_from` and make sure only the credential registry can
// call it - write tests to ensure this
// - define and implement IKudos interface including `give_kudos`
// - allow the credential registry to `mint` to a recipient
// - don't expose `transfer` only `transfer_from` and make sure only the credential registry can
// call it - write tests to ensure this
#[abi(embed_v0)]
impl Kudos of IKudos<ContractState> {
fn give_kudos(
ref self: ContractState,
amount: felt252,
sender_credentials: felt252,
receiver_credentials: felt252,
description: felt252,
) {}
}
}
Loading

0 comments on commit 639f852

Please sign in to comment.