diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..63fd76d --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,35 @@ +# Code of Conduct + +## Our Pledge + +We pledge to make participation in our project and community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information without explicit permission +- Other conduct which could reasonably be considered inappropriate + +## Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the project team. All complaints will be reviewed and investigated promptly and fairly. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..0848430 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,55 @@ +# Contributing Guidelines + +Thank you for considering contributing to the Bitcoin Yield Aggregator! + +## How to Contribute + +1. Fork the repository +2. Create a feature branch +3. Commit your changes +4. Push to your branch +5. Open a Pull Request + +## Development Process + +### Smart Contract Development + +1. Follow Clarity best practices +2. Maintain comprehensive test coverage +3. Document all functions and state changes +4. Verify security considerations + +### Testing + +- Write unit tests for all functions +- Include integration tests +- Test edge cases and failure scenarios +- Verify gas optimization + +### Documentation + +- Update technical documentation +- Add inline code comments +- Update README if needed +- Document breaking changes + +## Pull Request Process + +1. Update documentation +2. Add tests for new features +3. Ensure CI passes +4. Get review from maintainers +5. Address feedback + +## Security + +- Report security issues privately +- Follow responsible disclosure +- See SECURITY.md for details + +## Code Style + +- Follow Clarity style guide +- Use meaningful variable names +- Keep functions focused and small +- Add appropriate error handling diff --git a/Clarinet.toml b/Clarinet.toml index 55283db..69a0789 100644 --- a/Clarinet.toml +++ b/Clarinet.toml @@ -1,20 +1,22 @@ - [project] name = "bitcoin_yield_aggregator" authors = [] +description = "" telemetry = true +requirements = [] +[contracts.btc-yield-aggregator] +path = "contracts/btc-yield-aggregator.clar" +depends_on = [] + +[repl] +costs_version = 2 +parser_version = 2 + [repl.analysis] passes = ["check_checker"] + [repl.analysis.check_checker] -# If true, inputs are trusted after tx_sender has been checked. +strict = false trusted_sender = false -# If true, inputs are trusted after contract-caller has been checked. trusted_caller = false -# If true, untrusted data may be passed into a private function without a -# warning, if it gets checked inside. This check will also propagate up to the -# caller. callee_filter = false - -# [contracts.counter] -# path = "contracts/counter.clar" -# depends_on = [] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6fde465 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +MIT License + +Copyright (c) 2024 David Akuma +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7cb7dd5 --- /dev/null +++ b/README.md @@ -0,0 +1,88 @@ +# Bitcoin Yield Aggregator + +A secure and efficient DeFi yield strategy management system built on Bitcoin using Clarity smart contracts. + +## Overview + +The Bitcoin Yield Aggregator enables users to: + +- Deposit tokens into various yield-generating protocols +- Manage protocol allocations dynamically +- Earn and claim rewards based on protocol performance +- Benefit from automated strategy rebalancing + +## Key Features + +- **Protocol Management**: Add, update, and manage yield-generating protocols +- **Token Integration**: SIP-010 compliant token support with whitelisting +- **Secure Deposits**: Rate-limited deposits with comprehensive validation +- **Dynamic Rewards**: APY-based reward calculation and distribution +- **Emergency Controls**: Emergency shutdown mechanism for risk management +- **Rate Limiting**: Protection against abuse through operation rate limiting + +## Security Features + +- Protocol whitelisting +- Emergency shutdown mechanism +- Rate limiting +- Comprehensive input validation +- Balance verification +- SIP-010 compliance checks + +## Getting Started + +### Prerequisites + +- Stacks blockchain environment +- SIP-010 compliant tokens +- Clarity smart contract knowledge + +### Contract Deployment + +1. Deploy the contract to the Stacks blockchain +2. Set initial parameters (platform fee, deposit limits) +3. Whitelist supported tokens +4. Add yield-generating protocols + +### Usage + +```clarity +;; Deposit tokens +(contract-call? .yield-aggregator deposit token-trait amount) + +;; Withdraw tokens +(contract-call? .yield-aggregator withdraw token-trait amount) + +;; Claim rewards +(contract-call? .yield-aggregator claim-rewards token-trait) +``` + +## Architecture + +The contract is structured into several key components: + +- Protocol Management +- Token Management +- Deposit/Withdrawal Handling +- Reward Distribution +- Administrative Controls + +## Technical Documentation + +For detailed technical specifications, see [Technical Specification](docs/technical-specification.md) + +## Security + +See [SECURITY.md](SECURITY.md) for security policies and procedures. + +## Contributing + +Please read [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines. + +## License + +This project is licensed under the MIT License - see [LICENSE](LICENSE) for details. + +## Code of Conduct + +Please read our [Code of Conduct](CODE_OF_CONDUCT.md) for community guidelines. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..19c0250 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,44 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| 1.0.x | :white_check_mark: | + +## Reporting a Vulnerability + +1. **Do Not** file a public issue +2. Email davidakuma30@gmail.com + +3. Include detailed description +4. We will respond within 48 hours +5. Please allow time for fix before disclosure + +## Security Measures + +- Regular security audits +- Comprehensive testing +- Rate limiting +- Input validation +- Balance verification +- Emergency shutdown mechanism + +## Best Practices + +- Use whitelisted tokens only +- Monitor transaction limits +- Verify contract state +- Check return values +- Validate inputs + +## Emergency Procedures + +In case of critical vulnerabilities: + +1. Emergency shutdown activated +2. All operations suspended +3. Funds secured +4. Issue investigated +5. Fix implemented +6. System gradually restored diff --git a/contracts/btc-yield-aggregator.clar b/contracts/btc-yield-aggregator.clar new file mode 100644 index 0000000..ac45382 --- /dev/null +++ b/contracts/btc-yield-aggregator.clar @@ -0,0 +1,500 @@ +;; Bitcoin Yield Aggregator +;; +;; A secure and efficient DeFi yield strategy management system that enables users to: +;; - Deposit tokens into various yield-generating protocols +;; - Manage protocol allocations dynamically +;; - Earn and claim rewards based on protocol performance +;; - Benefit from automated strategy rebalancing +;; +;; Security Features: +;; - Protocol whitelisting +;; - Emergency shutdown mechanism +;; - Rate limiting +;; - Comprehensive input validation +;; - Balance verification +;; - SIP-010 compliance checks + +;; Principal Constants +(define-constant contract-owner tx-sender) + +;; Error Constants +(define-constant ERR-NOT-AUTHORIZED (err u1000)) +(define-constant ERR-INVALID-AMOUNT (err u1001)) +(define-constant ERR-INSUFFICIENT-BALANCE (err u1002)) +(define-constant ERR-PROTOCOL-NOT-WHITELISTED (err u1003)) +(define-constant ERR-STRATEGY-DISABLED (err u1004)) +(define-constant ERR-MAX-DEPOSIT-REACHED (err u1005)) +(define-constant ERR-MIN-DEPOSIT-NOT-MET (err u1006)) +(define-constant ERR-INVALID-PROTOCOL-ID (err u1007)) +(define-constant ERR-PROTOCOL-EXISTS (err u1008)) +(define-constant ERR-INVALID-APY (err u1009)) +(define-constant ERR-INVALID-NAME (err u1010)) +(define-constant ERR-INVALID-TOKEN (err u1011)) +(define-constant ERR-TOKEN-NOT-WHITELISTED (err u1012)) +(define-constant ERR-ZERO-AMOUNT (err u1013)) +(define-constant ERR-INVALID-USER (err u1014)) +(define-constant ERR-ALREADY-WHITELISTED (err u1015)) +(define-constant ERR-AMOUNT-TOO-LARGE (err u1016)) +(define-constant ERR-INVALID-STATE (err u1017)) +(define-constant ERR-RATE-LIMITED (err u1018)) + +;; Protocol Constants +(define-constant PROTOCOL-ACTIVE true) +(define-constant PROTOCOL-INACTIVE false) +(define-constant MAX-PROTOCOL-ID u100) +(define-constant MAX-APY u10000) +(define-constant MIN-APY u0) +(define-constant MAX-TOKEN-TRANSFER u1000000000000) +(define-constant MIN-REQUIRED-RESPONSES u3) + +;; State Variables +(define-data-var total-tvl uint u0) +(define-data-var platform-fee-rate uint u100) +(define-data-var min-deposit uint u100000) +(define-data-var max-deposit uint u1000000000) +(define-data-var emergency-shutdown bool false) + +;; Data Maps +(define-map user-deposits + { user: principal } + { amount: uint, last-deposit-block: uint }) + +(define-map user-rewards + { user: principal } + { pending: uint, claimed: uint }) + +(define-map protocols + { protocol-id: uint } + { name: (string-ascii 64), active: bool, apy: uint }) + +(define-map strategy-allocations + { protocol-id: uint } + { allocation: uint }) + +(define-map whitelisted-tokens + { token: principal } + { approved: bool }) + +(define-map user-operations + { user: principal } + { last-operation: uint, count: uint }) + +;; SIP-010 Token Interface +(define-trait sip-010-trait + ( + (transfer (uint principal principal (optional (buff 34))) (response bool uint)) + (get-balance (principal) (response uint uint)) + (get-decimals () (response uint uint)) + (get-name () (response (string-ascii 32) uint)) + (get-symbol () (response (string-ascii 32) uint)) + (get-total-supply () (response uint uint)) + ) +) + +;; Authorization Functions +(define-private (is-contract-owner) + (is-eq tx-sender contract-owner) +) + +;; Validation Functions +(define-private (is-valid-protocol-id (protocol-id uint)) + (and + (> protocol-id u0) + (<= protocol-id MAX-PROTOCOL-ID) + ) +) + +(define-private (is-valid-apy (apy uint)) + (and + (>= apy MIN-APY) + (<= apy MAX-APY) + ) +) + +(define-private (is-valid-name (name (string-ascii 64))) + (and + (not (is-eq name "")) + (<= (len name) u64) + ) +) + +(define-private (protocol-exists (protocol-id uint)) + (is-some (map-get? protocols { protocol-id: protocol-id })) +) + +(define-private (check-valid-amount (amount uint)) + (begin + (asserts! (> amount u0) ERR-ZERO-AMOUNT) + (asserts! (<= amount MAX-TOKEN-TRANSFER) ERR-AMOUNT-TOO-LARGE) + (ok amount) + ) +) + +(define-private (check-valid-user (user principal)) + (begin + (asserts! (not (is-eq user (as-contract tx-sender))) ERR-INVALID-USER) + (ok user) + ) +) + +(define-private (check-contract-state) + (begin + (asserts! (not (var-get emergency-shutdown)) ERR-STRATEGY-DISABLED) + (ok true) + ) +) + +;; Protocol Management Functions +(define-public (add-protocol (protocol-id uint) (name (string-ascii 64)) (initial-apy uint)) + (begin + (asserts! (is-contract-owner) ERR-NOT-AUTHORIZED) + (asserts! (is-valid-protocol-id protocol-id) ERR-INVALID-PROTOCOL-ID) + (asserts! (not (protocol-exists protocol-id)) ERR-PROTOCOL-EXISTS) + (asserts! (is-valid-name name) ERR-INVALID-NAME) + (asserts! (is-valid-apy initial-apy) ERR-INVALID-APY) + + (map-set protocols { protocol-id: protocol-id } + { + name: name, + active: PROTOCOL-ACTIVE, + apy: initial-apy + } + ) + (map-set strategy-allocations { protocol-id: protocol-id } { allocation: u0 }) + (ok true) + ) +) + +(define-public (update-protocol-status (protocol-id uint) (active bool)) + (begin + (asserts! (is-contract-owner) ERR-NOT-AUTHORIZED) + (asserts! (is-valid-protocol-id protocol-id) ERR-INVALID-PROTOCOL-ID) + (asserts! (protocol-exists protocol-id) ERR-INVALID-PROTOCOL-ID) + + (let ((protocol (unwrap-panic (get-protocol protocol-id)))) + (map-set protocols { protocol-id: protocol-id } + (merge protocol { active: active }) + ) + ) + (ok true) + ) +) + +(define-public (update-protocol-apy (protocol-id uint) (new-apy uint)) + (begin + (asserts! (is-contract-owner) ERR-NOT-AUTHORIZED) + (asserts! (is-valid-protocol-id protocol-id) ERR-INVALID-PROTOCOL-ID) + (asserts! (protocol-exists protocol-id) ERR-INVALID-PROTOCOL-ID) + (asserts! (is-valid-apy new-apy) ERR-INVALID-APY) + + (let ((protocol (unwrap-panic (get-protocol protocol-id)))) + (map-set protocols { protocol-id: protocol-id } + (merge protocol { apy: new-apy }) + ) + ) + (ok true) + ) +) + +;; Token Management Functions +(define-private (validate-token (token-trait )) + (let + ( + (token-contract (contract-of token-trait)) + (token-info (map-get? whitelisted-tokens { token: token-contract })) + ) + (asserts! (is-some token-info) ERR-TOKEN-NOT-WHITELISTED) + (asserts! (get approved (unwrap-panic token-info)) ERR-PROTOCOL-NOT-WHITELISTED) + + (let + ( + (name-response (try! (contract-call? token-trait get-name))) + (symbol-response (try! (contract-call? token-trait get-symbol))) + (decimals-response (try! (contract-call? token-trait get-decimals))) + ) + (asserts! (and + (> (len name-response) u0) + (> (len symbol-response) u0) + (>= decimals-response u0) + ) ERR-INVALID-TOKEN) + ) + + (ok token-contract) + ) +) + +;; Deposit Management Functions +(define-public (deposit (token-trait ) (amount uint)) + (let + ( + (user-principal tx-sender) + (current-deposit (default-to { amount: u0, last-deposit-block: u0 } + (map-get? user-deposits { user: user-principal }))) + ) + (try! (check-valid-amount amount)) + (try! (check-valid-user user-principal)) + (try! (validate-token-extended token-trait)) + (try! (check-rate-limit user-principal)) + (try! (check-contract-state)) + + (asserts! (>= amount (var-get min-deposit)) ERR-MIN-DEPOSIT-NOT-MET) + (asserts! (<= (+ amount (get amount current-deposit)) (var-get max-deposit)) ERR-MAX-DEPOSIT-REACHED) + + (let ((user-balance (try! (contract-call? token-trait get-balance user-principal)))) + (asserts! (>= user-balance amount) ERR-INSUFFICIENT-BALANCE) + ) + + (try! (safe-token-transfer token-trait amount user-principal (as-contract tx-sender))) + + (map-set user-deposits + { user: user-principal } + { + amount: (+ amount (get amount current-deposit)), + last-deposit-block: block-height + }) + + (var-set total-tvl (+ (var-get total-tvl) amount)) + (update-rate-limit user-principal) + + (try! (rebalance-protocols)) + (ok true) + ) +) + +(define-public (withdraw (token-trait ) (amount uint)) + (let + ( + (user-principal tx-sender) + (current-deposit (default-to { amount: u0, last-deposit-block: u0 } + (map-get? user-deposits { user: user-principal }))) + ) + (try! (check-valid-amount amount)) + (try! (check-valid-user user-principal)) + (try! (validate-token-extended token-trait)) + (try! (check-rate-limit user-principal)) + (asserts! (<= amount (get amount current-deposit)) ERR-INSUFFICIENT-BALANCE) + + (let ((contract-balance (try! (contract-call? token-trait get-balance (as-contract tx-sender))))) + (asserts! (>= contract-balance amount) ERR-INSUFFICIENT-BALANCE) + ) + + (map-set user-deposits + { user: user-principal } + { + amount: (- (get amount current-deposit) amount), + last-deposit-block: (get last-deposit-block current-deposit) + }) + + (var-set total-tvl (- (var-get total-tvl) amount)) + (update-rate-limit user-principal) + + (as-contract + (try! (safe-token-transfer token-trait amount tx-sender user-principal))) + + (ok true) + ) +) + +;; Token Transfer Helper +(define-private (safe-token-transfer (token-trait ) (amount uint) (sender principal) (recipient principal)) + (begin + (asserts! (not (var-get emergency-shutdown)) ERR-STRATEGY-DISABLED) + (try! (check-valid-amount amount)) + (try! (check-valid-user recipient)) + (try! (validate-token token-trait)) + + (let ((sender-balance (unwrap-panic (contract-call? token-trait get-balance sender)))) + (asserts! (>= sender-balance amount) ERR-INSUFFICIENT-BALANCE) + ) + (contract-call? token-trait transfer amount sender recipient none) + ) +) + +;; Reward Management Functions +(define-private (calculate-rewards (user principal) (blocks uint)) + (let + ( + (user-deposit (unwrap-panic (get-user-deposit user))) + (weighted-apy (get-weighted-apy)) + ) + (/ (* (get amount user-deposit) weighted-apy blocks) (* u10000 u144 u365)) + ) +) + +(define-public (claim-rewards (token-trait )) + (let + ( + (user-principal tx-sender) + (rewards (calculate-rewards user-principal (- block-height + (get last-deposit-block (unwrap-panic (get-user-deposit user-principal)))))) + ) + (try! (validate-token-extended token-trait)) + (try! (check-rate-limit user-principal)) + (asserts! (> rewards u0) ERR-INVALID-AMOUNT) + + (let ((contract-balance (try! (contract-call? token-trait get-balance (as-contract tx-sender))))) + (asserts! (>= contract-balance rewards) ERR-INSUFFICIENT-BALANCE) + ) + + (map-set user-rewards + { user: user-principal } + { + pending: u0, + claimed: (+ rewards + (get claimed (default-to { pending: u0, claimed: u0 } + (map-get? user-rewards { user: user-principal })))) + }) + + (update-rate-limit user-principal) + + (as-contract + (try! (safe-token-transfer token-trait rewards tx-sender user-principal))) + + (ok rewards) + ) +) + +;; Protocol Optimization Functions +(define-private (rebalance-protocols) + (let + ( + (total-allocations (fold + (map get-protocol-allocation (get-protocol-list)) u0)) + ) + (asserts! (<= total-allocations u10000) ERR-INVALID-AMOUNT) + (ok true) + ) +) + +(define-private (get-weighted-apy) + (fold + (map get-weighted-protocol-apy (get-protocol-list)) u0) +) + +(define-private (get-weighted-protocol-apy (protocol-id uint)) + (let + ( + (protocol (unwrap-panic (get-protocol protocol-id))) + (allocation (get allocation (unwrap-panic + (map-get? strategy-allocations { protocol-id: protocol-id })))) + ) + (if (get active protocol) + (/ (* (get apy protocol) allocation) u10000) + u0 + ) + ) +) + +;; Read-Only Functions +(define-read-only (get-protocol (protocol-id uint)) + (map-get? protocols { protocol-id: protocol-id }) +) + +(define-read-only (get-user-deposit (user principal)) + (map-get? user-deposits { user: user }) +) + +(define-read-only (get-total-tvl) + (var-get total-tvl) +) + +(define-read-only (is-whitelisted (token )) + (default-to false (get approved (map-get? whitelisted-tokens { token: (contract-of token) }))) +) + +;; Administrative Functions +(define-public (set-platform-fee (new-fee uint)) + (begin + (asserts! (is-contract-owner) ERR-NOT-AUTHORIZED) + (asserts! (<= new-fee u1000) ERR-INVALID-AMOUNT) + (var-set platform-fee-rate new-fee) + (ok true) + ) +) + +(define-public (set-emergency-shutdown (shutdown bool)) + (begin + (asserts! (is-contract-owner) ERR-NOT-AUTHORIZED) + (asserts! (not (is-eq shutdown (var-get emergency-shutdown))) ERR-INVALID-STATE) + (print { event: "emergency-shutdown", status: shutdown }) + (var-set emergency-shutdown shutdown) + (ok true) + ) +) + +(define-public (whitelist-token (token )) + (begin + (asserts! (is-contract-owner) ERR-NOT-AUTHORIZED) + (let + ( + (token-contract (contract-of token)) + ) + (asserts! (not (is-whitelisted token)) ERR-ALREADY-WHITELISTED) + + (try! (contract-call? token get-name)) + (try! (contract-call? token get-symbol)) + (try! (contract-call? token get-decimals)) + (try! (contract-call? token get-total-supply)) + + (map-set whitelisted-tokens { token: token-contract } { approved: true }) + (print { event: "token-whitelisted", token: token-contract }) + (ok true) + ) + ) +) + +;; Helper Functions +(define-private (get-protocol-list) + (list u1 u2 u3 u4 u5) +) + +(define-private (get-protocol-allocation (protocol-id uint)) + (get allocation (default-to { allocation: u0 } + (map-get? strategy-allocations { protocol-id: protocol-id }))) +) + +(define-private (check-rate-limit (user principal)) + (let ((user-ops (default-to { last-operation: u0, count: u0 } + (map-get? user-operations { user: user })))) + (asserts! (or + (> block-height (+ (get last-operation user-ops) u144)) + (< (get count user-ops) u10) + ) ERR-RATE-LIMITED) + (ok true) + ) +) + +(define-private (update-rate-limit (user principal)) + (let ((user-ops (default-to { last-operation: u0, count: u0 } + (map-get? user-operations { user: user })))) + (map-set user-operations + { user: user } + { + last-operation: block-height, + count: (if (> block-height (+ (get last-operation user-ops) u144)) + u1 + (+ (get count user-ops) u1)) + } + ) + ) +) + +(define-private (validate-token-extended (token-trait )) + (let + ( + (token-contract (contract-of token-trait)) + (token-info (map-get? whitelisted-tokens { token: token-contract })) + ) + (try! (validate-token token-trait)) + + (asserts! (not (is-eq token-contract (as-contract tx-sender))) ERR-INVALID-TOKEN) + + (let ((total-supply (try! (contract-call? token-trait get-total-supply)))) + (asserts! (> total-supply u0) ERR-INVALID-TOKEN) + ) + + (let ((decimals (try! (contract-call? token-trait get-decimals)))) + (asserts! (and (>= decimals u6) (<= decimals u18)) ERR-INVALID-TOKEN) + ) + + (ok token-contract) + ) +) \ No newline at end of file diff --git a/docs/technical-specification.md b/docs/technical-specification.md new file mode 100644 index 0000000..f1fca78 --- /dev/null +++ b/docs/technical-specification.md @@ -0,0 +1,112 @@ +# Technical Specification + +## Contract Overview + +The Bitcoin Yield Aggregator is a DeFi protocol for managing yield-generating strategies on Bitcoin using Clarity smart contracts. + +## Core Components + +### State Management + +```clarity +;; TVL and Platform Parameters +(define-data-var total-tvl uint u0) +(define-data-var platform-fee-rate uint u100) +(define-data-var min-deposit uint u100000) +(define-data-var max-deposit uint u1000000000) +(define-data-var emergency-shutdown bool false) +``` + +### Data Structures + +```clarity +;; User Deposits +(define-map user-deposits + { user: principal } + { amount: uint, last-deposit-block: uint }) + +;; Protocol Configuration +(define-map protocols + { protocol-id: uint } + { name: (string-ascii 64), active: bool, apy: uint }) +``` + +## Key Functions + +### Deposit Management + +- `deposit`: Process user deposits +- `withdraw`: Handle withdrawals +- `safe-token-transfer`: Secure token transfers + +### Reward System + +- `calculate-rewards`: Compute user rewards +- `claim-rewards`: Process reward claims +- `get-weighted-apy`: Calculate effective APY + +### Protocol Management + +- `add-protocol`: Add new protocols +- `update-protocol-status`: Manage protocol state +- `update-protocol-apy`: Update yield rates + +## Security Features + +### Rate Limiting + +- Maximum 10 operations per 144 blocks +- Cooldown period enforcement +- Operation counting + +### Input Validation + +- Amount bounds checking +- Protocol ID validation +- Token compliance verification + +### Balance Verification + +- User balance checks +- Contract balance verification +- TVL monitoring + +## Error Handling + +### Error Codes + +```clarity +(define-constant ERR-NOT-AUTHORIZED (err u1000)) +(define-constant ERR-INVALID-AMOUNT (err u1001)) +;; ... additional error codes +``` + +## Integration Guide + +### Token Requirements + +- SIP-010 compliance +- Minimum 6 decimals +- Maximum 18 decimals +- Non-zero total supply + +### Protocol Integration + +1. Protocol whitelisting +2. APY configuration +3. Allocation setup +4. Status management + +## Performance Considerations + +### Gas Optimization + +- Efficient data structures +- Minimal state changes +- Optimized calculations + +### Scalability + +- Rate limiting design +- Balance thresholds +- Protocol limits diff --git a/tests/btc-yielld-aggregator_test.ts b/tests/btc-yielld-aggregator_test.ts new file mode 100644 index 0000000..9a18ae0 --- /dev/null +++ b/tests/btc-yielld-aggregator_test.ts @@ -0,0 +1,26 @@ + +import { Clarinet, Tx, Chain, Account, types } from 'https://deno.land/x/clarinet@v0.14.0/index.ts'; +import { assertEquals } from 'https://deno.land/std@0.90.0/testing/asserts.ts'; + +Clarinet.test({ + name: "Ensure that <...>", + async fn(chain: Chain, accounts: Map) { + let block = chain.mineBlock([ + /* + * Add transactions with: + * Tx.contractCall(...) + */ + ]); + assertEquals(block.receipts.length, 0); + assertEquals(block.height, 2); + + block = chain.mineBlock([ + /* + * Add transactions with: + * Tx.contractCall(...) + */ + ]); + assertEquals(block.receipts.length, 0); + assertEquals(block.height, 3); + }, +});