diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e9e4f81 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,277 @@ +# Contributing to Utility-Drip-Contracts + +Welcome to the Utility-Drip-Contracts project! This guide will help you contribute effectively, whether you're working on hardware (C++/Arduino) or smart contracts (Soroban/Rust). + +## Project Overview + +Utility-Drip-Contracts is a utility billing system built on Stellar that allows: +- Individual meter billing and management +- Group billing for property managers +- Real-time balance monitoring +- Automated payment processing + +## Development Areas + +### ๐ Hardware Development (C++/Arduino) +Hardware components handle the physical meter readings and communicate with the blockchain. + +### โก Smart Contract Development (Rust/Soroban) +Smart contracts handle billing logic, payment processing, and account management. + +--- + +## Hardware Development Guidelines + +### ๐ ๏ธ Development Environment + +**Required Tools:** +- Arduino IDE 2.0+ or PlatformIO +- C++17 compatible compiler +- ESP32 or Arduino-compatible hardware +- Stellar SDK for embedded systems (if available) + +**Recommended Setup:** +```bash +# For PlatformIO users +pio project init --board esp32dev +pio lib install "Stellar SDK" +``` + +### ๐ Hardware Standards + +**Meter Reading Specifications:** +- Sample rate: Minimum 1 reading per second +- Accuracy: ยฑ1% for power measurements +- Data format: JSON over MQTT/HTTP +- Power consumption: < 100mA during operation + +**Communication Protocol:** +```json +{ + "meter_id": 12345, + "timestamp": 1640995200, + "reading": 1250, + "unit": "watt_hours", + "signature": "0x..." +} +``` + +### ๐ง Code Standards + +**C++ Guidelines:** +- Use `camelCase` for variables +- Use `PascalCase` for classes +- Use `UPPER_SNAKE_CASE` for constants +- Include comprehensive error handling +- Memory management: prefer RAII patterns + +**Example Structure:** +```cpp +class UtilityMeter { +private: + uint32_t meterId; + float currentReading; + StellarClient* stellarClient; + +public: + UtilityMeter(uint32_t id, StellarClient* client); + bool takeReading(); + bool submitToBlockchain(); + float getCurrentReading() const; +}; +``` + +### ๐งช Testing Hardware + +**Unit Testing:** +- Use ArduinoUnit or GoogleTest framework +- Test meter accuracy with known loads +- Validate communication protocols +- Test error recovery mechanisms + +**Integration Testing:** +- Test against testnet blockchain +- Validate contract interactions +- Test network connectivity issues +- Power consumption validation + +### ๐ฆ Hardware Deployment + +**Pre-deployment Checklist:** +- [ ] Meter calibration completed +- [ ] Network connectivity verified +- [ ] Testnet transactions successful +- [ ] Power consumption within limits +- [ ] Error handling tested +- [ ] Firmware version documented + +--- + +## Smart Contract Development Guidelines + +### ๐ ๏ธ Development Environment + +**Required Tools:** +- Rust 1.70+ +- Soroban CLI +- Stellar Testnet access + +**Setup:** +```bash +# Install Soroban CLI +cargo install soroban-cli + +# Build contracts +make build + +# Run tests +make test +``` + +### ๐ Contract Standards + +**Gas Optimization:** +- Minimize storage operations +- Use efficient data structures +- Batch operations when possible +- Consider gas costs in design + +**Security Guidelines:** +- Validate all inputs +- Use proper access controls +- Implement reentrancy protection +- Audit critical functions + +### ๐งช Testing Contracts + +**Test Coverage:** +- Unit tests for all functions +- Integration tests for workflows +- Edge case testing +- Gas usage analysis + +--- + +## ๐ Contribution Workflow + +### 1. Fork and Clone +```bash +git clone https://github.com/your-username/Utility-Drip-Contracts.git +cd Utility-Drip-Contracts +``` + +### 2. Create Feature Branch +```bash +git checkout -b feature/hardware-meter-optimization +``` + +### 3. Development + +**For Hardware Changes:** +- Modify C++/Arduino code in `hardware/` directory +- Update documentation +- Add tests +- Verify against testnet + +**For Contract Changes:** +- Modify Rust code in `contracts/` directory +- Update tests +- Run gas analysis +- Document changes + +### 4. Testing +```bash +# Hardware tests +cd hardware && pio test + +# Contract tests +cd contracts && cargo test + +# Integration tests +make integration-test +``` + +### 5. Documentation +- Update README.md if needed +- Add inline code comments +- Update API documentation +- Include hardware specifications + +### 6. Pull Request +- Create descriptive PR title +- Describe changes in detail +- Include test results +- Tag relevant reviewers + +## ๐ท๏ธ Label Guidelines + +**Hardware PRs:** +- `hardware`: For hardware-related changes +- `arduino`: For Arduino-specific code +- `embedded`: For embedded systems work + +**Contract PRs:** +- `contracts`: For smart contract changes +- `soroban`: For Soroban-specific features +- `backend`: For backend logic + +**General:** +- `bugfix`: For bug fixes +- `feature`: For new features +- `documentation`: For documentation updates +- `testing`: For test improvements + +## ๐ Bug Reports + +**Hardware Bugs:** +Include: +- Hardware model and firmware version +- Environmental conditions +- Error logs +- Reproduction steps +- Expected vs actual behavior + +**Contract Bugs:** +Include: +- Contract version +- Transaction hash +- Input parameters +- Error message +- Expected vs actual behavior + +## ๐ก Feature Requests + +**Hardware Features:** +- Describe the hardware capability +- Explain the user benefit +- Consider power/processing constraints +- Include implementation suggestions + +**Contract Features:** +- Describe the functionality +- Explain the use case +- Consider gas implications +- Include API design suggestions + +## ๐ค Community Guidelines + +- Be respectful and inclusive +- Provide constructive feedback +- Help others learn +- Follow the code of conduct +- Focus on what's best for the community + +## ๐ Get Help + +- **Discord**: [Utility-Drip Community](https://discord.gg/utilitydrip) +- **GitHub Issues**: For bug reports and feature requests +- **Documentation**: Check the `/docs` directory +- **Examples**: See `/examples` directory + +## ๐ License + +By contributing, you agree that your contributions will be licensed under the same license as the project. + +--- + +Thank you for contributing to Utility-Drip-Contracts! ๐ diff --git a/contracts/utility_contracts/src/gas_estimator.rs b/contracts/utility_contracts/src/gas_estimator.rs new file mode 100644 index 0000000..3b93720 --- /dev/null +++ b/contracts/utility_contracts/src/gas_estimator.rs @@ -0,0 +1,134 @@ +use soroban_sdk::{Env, Address}; + +pub struct GasCostEstimator; + +impl GasCostEstimator { + // Gas costs for different operations (in stroops) + const REGISTER_METER: i128 = 10_000_000; // 0.1 XLM + const TOP_UP: i128 = 5_000_000; // 0.05 XLM + const CLAIM: i128 = 8_000_000; // 0.08 XLM + const UPDATE_HEARTBEAT: i128 = 3_000_000; // 0.03 XLM + const GROUP_TOP_UP_PER_METER: i128 = 6_000_000; // 0.06 XLM per meter + const EMERGENCY_SHUTDOWN: i128 = 2_000_000; // 0.02 XLM + + // Estimated monthly operations per meter + const CLAIMS_PER_MONTH: u32 = 30; // Assuming daily claims + const HEARTBEATS_PER_MONTH: u32 = 720; // Every hour for 30 days + const TOP_UPS_PER_MONTH: u32 = 4; // Weekly top-ups + + pub fn estimate_meter_monthly_cost( + _env: &Env, + is_group_meter: bool, + meters_in_group: u32, + ) -> i128 { + let mut monthly_cost = Self::REGISTER_METER; // One-time registration + + // Add recurring costs + monthly_cost += (Self::CLAIM as u32 * Self::CLAIMS_PER_MONTH) as i128; + monthly_cost += (Self::UPDATE_HEARTBEAT as u32 * Self::HEARTBEATS_PER_MONTH) as i128; + monthly_cost += (Self::TOP_UP as u32 * Self::TOP_UPS_PER_MONTH) as i128; + + // For group meters, adjust top-up costs + if is_group_meter { + monthly_cost = monthly_cost - (Self::TOP_UP as u32 * Self::TOP_UPS_PER_MONTH) as i128; + monthly_cost += (Self::GROUP_TOP_UP_PER_METER as u32 * Self::TOP_UPS_PER_MONTH) as i128; + } + + monthly_cost + } + + pub fn estimate_provider_monthly_cost( + _env: &Env, + number_of_meters: u32, + percentage_group_meters: f32, + ) -> i128 { + let group_meters = (number_of_meters as f32 * percentage_group_meters) as u32; + let individual_meters = number_of_meters - group_meters; + + let group_cost = if group_meters > 0 { + // Assume average of 5 meters per group + let groups = group_meters / 5; + if groups > 0 { + Self::estimate_meter_monthly_cost(_env, true, 5) * groups as i128 + } else { + 0 + } + } else { + 0 + }; + + let individual_cost = Self::estimate_meter_monthly_cost(_env, false, 0) * individual_meters as i128; + + group_cost + individual_cost + } + + pub fn estimate_large_scale_cost( + env: &Env, + number_of_meters: u32, + group_billing_enabled: bool, + ) -> LargeScaleCostEstimate { + let percentage_group = if group_billing_enabled { 0.8 } else { 0.0 }; // 80% in groups if enabled + let monthly_cost = Self::estimate_provider_monthly_cost(env, number_of_meters, percentage_group); + + let annual_cost = monthly_cost * 12; + let cost_per_meter = monthly_cost / number_of_meters as i128; + + // Convert to XLM (1 XLM = 10,000,000 stroops) + let monthly_xlm = monthly_cost / 10_000_000; + let annual_xlm = annual_cost / 10_000_000; + let cost_per_meter_xlm = cost_per_meter / 10_000_000; + + LargeScaleCostEstimate { + number_of_meters, + monthly_cost_stroops: monthly_cost, + annual_cost_stroops: annual_cost, + cost_per_meter_stroops: cost_per_meter, + monthly_cost_xlm, + annual_cost_xlm, + cost_per_meter_xlm, + group_billing_enabled, + } + } + + pub fn get_operation_cost(operation: &str) -> i128 { + match operation { + "register_meter" => Self::REGISTER_METER, + "top_up" => Self::TOP_UP, + "claim" => Self::CLAIM, + "update_heartbeat" => Self::UPDATE_HEARTBEAT, + "group_top_up" => Self::GROUP_TOP_UP_PER_METER, + "emergency_shutdown" => Self::EMERGENCY_SHUTDOWN, + _ => 0, + } + } +} + +#[contracttype] +#[derive(Clone)] +pub struct LargeScaleCostEstimate { + pub number_of_meters: u32, + pub monthly_cost_stroops: i128, + pub annual_cost_stroops: i128, + pub cost_per_meter_stroops: i128, + pub monthly_cost_xlm: i128, + pub annual_cost_xlm: i128, + pub cost_per_meter_xlm: i128, + pub group_billing_enabled: bool, +} + +impl LargeScaleCostEstimate { + pub fn get_summary(&self) -> String { + format!( + "Cost Analysis for {} meters:\n\ + Monthly: {} XLM ({} per meter)\n\ + Annual: {} XLM ({} per meter)\n\ + Group Billing: {}", + self.number_of_meters, + self.monthly_cost_xlm, + self.cost_per_meter_xlm, + self.annual_cost_xlm, + self.cost_per_meter_xlm, + if self.group_billing_enabled { "Enabled" } else { "Disabled" } + ) + } +} diff --git a/contracts/utility_contracts/src/lib.rs b/contracts/utility_contracts/src/lib.rs index b27164c..69f1d3f 100644 --- a/contracts/utility_contracts/src/lib.rs +++ b/contracts/utility_contracts/src/lib.rs @@ -1,6 +1,9 @@ #![no_std] use soroban_sdk::{contract, contracttype, contractimpl, Address, Env, token, Symbol}; +mod gas_estimator; +use gas_estimator::{GasCostEstimator, LargeScaleCostEstimate}; + #[contracttype] #[derive(Clone)] pub struct Meter { @@ -15,6 +18,34 @@ pub struct Meter { pub last_claim_time: u64, pub claimed_this_hour: i128, pub heartbeat: u64, + pub parent_account: Option
, +} + +#[contracttype] +#[derive(Clone)] +pub struct BillingGroup { + pub parent_account: Address, + pub child_meters: Vec