diff --git a/Cargo.toml b/Cargo.toml index e51f487..0b55f1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ members = [ "src/batch", "src/utils", "src/flash_loan", + "src/kyc" "src/staking" ] resolver = "2" diff --git a/src/kyc/Cargo.toml b/src/kyc/Cargo.toml new file mode 100644 index 0000000..c1709b7 --- /dev/null +++ b/src/kyc/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "kyc-verifier" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib"] +path = "lib.rs" +doctest = false + +[dependencies] +soroban-sdk = "22.0.0" + +[dev-dependencies] +soroban-sdk = { version = "22.0.0", features = ["testutils"] } diff --git a/src/kyc/lib.rs b/src/kyc/lib.rs new file mode 100644 index 0000000..c784496 --- /dev/null +++ b/src/kyc/lib.rs @@ -0,0 +1,57 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Address, Env, Bytes, BytesN}; + +#[contracttype] +pub enum DataKey { + Admin, + VerifierPubKey, + UserKyc(Address), // ExpiresAt (u64) +} + +#[contract] +pub struct KycVerifier; + +#[contractimpl] +impl KycVerifier { + pub fn initialize(env: Env, admin: Address, verifier_pubkey: BytesN<32>) { + if env.storage().instance().has(&DataKey::Admin) { + panic!("already initialized"); + } + admin.require_auth(); + env.storage().instance().set(&DataKey::Admin, &admin); + env.storage().instance().set(&DataKey::VerifierPubKey, &verifier_pubkey); + } + + pub fn set_kyc_status(env: Env, user: Address, signature: BytesN<64>, expires_at: u64) { + // KYC provider signs: user_addr + expires_at + let current_time = env.ledger().timestamp(); + assert!(expires_at > current_time, "proof expired"); + + let mut data = Bytes::new(&env); + data.append(&user.to_xdr(&env)); + data.append(&(expires_at as u128).to_be_bytes().as_slice().into()); // Example message data + + // In real cases, we'd hash the data or use a specific format. + // For simplicity, let's verify ed25519 signature. + let pubkey: BytesN<32> = env.storage().instance().get(&DataKey::VerifierPubKey).unwrap(); + + env.crypto().ed25519_verify(&pubkey, &data, &signature); + + env.storage().persistent().set(&DataKey::UserKyc(user.clone()), &expires_at); + env.events().publish((symbol_short!("kyc_set"), user), expires_at); + } + + pub fn is_kyc_valid(env: Env, user: Address) -> bool { + let current_time = env.ledger().timestamp(); + match env.storage().persistent().get::<_, u64>(&DataKey::UserKyc(user)) { + Some(expiry) => expiry > current_time, + None => false, + } + } + + pub fn update_verifier(env: Env, new_pubkey: BytesN<32>) { + let admin: Address = env.storage().instance().get(&DataKey::Admin).unwrap(); + admin.require_auth(); + env.storage().instance().set(&DataKey::VerifierPubKey, &new_pubkey); + } +}