From db32f1f341521e1edccd597f40acf97c8da6a734 Mon Sep 17 00:00:00 2001 From: nelsson007 Date: Fri, 27 Jun 2025 11:44:43 +0100 Subject: [PATCH] code for stacks --- Meme-Empire/.gitattributes | 3 + Meme-Empire/.gitignore | 13 + Meme-Empire/.vscode/settings.json | 4 + Meme-Empire/.vscode/tasks.json | 19 ++ Meme-Empire/Clarinet.toml | 23 ++ Meme-Empire/README | 203 ++++++++++++ Meme-Empire/contracts/Stacks-Meme.clar | 420 +++++++++++++++++++++++++ Meme-Empire/package.json | 23 ++ Meme-Empire/settings/Devnet.toml | 168 ++++++++++ Meme-Empire/tests/Stacks-Meme.test.ts | 21 ++ Meme-Empire/tsconfig.json | 26 ++ Meme-Empire/vitest.config.js | 42 +++ 12 files changed, 965 insertions(+) create mode 100644 Meme-Empire/.gitattributes create mode 100644 Meme-Empire/.gitignore create mode 100644 Meme-Empire/.vscode/settings.json create mode 100644 Meme-Empire/.vscode/tasks.json create mode 100644 Meme-Empire/Clarinet.toml create mode 100644 Meme-Empire/README create mode 100644 Meme-Empire/contracts/Stacks-Meme.clar create mode 100644 Meme-Empire/package.json create mode 100644 Meme-Empire/settings/Devnet.toml create mode 100644 Meme-Empire/tests/Stacks-Meme.test.ts create mode 100644 Meme-Empire/tsconfig.json create mode 100644 Meme-Empire/vitest.config.js diff --git a/Meme-Empire/.gitattributes b/Meme-Empire/.gitattributes new file mode 100644 index 0000000..da6a065 --- /dev/null +++ b/Meme-Empire/.gitattributes @@ -0,0 +1,3 @@ +tests/** linguist-vendored +vitest.config.js linguist-vendored +* text=lf diff --git a/Meme-Empire/.gitignore b/Meme-Empire/.gitignore new file mode 100644 index 0000000..76c2842 --- /dev/null +++ b/Meme-Empire/.gitignore @@ -0,0 +1,13 @@ + +**/settings/Mainnet.toml +**/settings/Testnet.toml +.cache/** +history.txt + +logs +*.log +npm-debug.log* +coverage +*.info +costs-reports.json +node_modules diff --git a/Meme-Empire/.vscode/settings.json b/Meme-Empire/.vscode/settings.json new file mode 100644 index 0000000..3062519 --- /dev/null +++ b/Meme-Empire/.vscode/settings.json @@ -0,0 +1,4 @@ + +{ + "files.eol": "\n" +} diff --git a/Meme-Empire/.vscode/tasks.json b/Meme-Empire/.vscode/tasks.json new file mode 100644 index 0000000..4dec0ff --- /dev/null +++ b/Meme-Empire/.vscode/tasks.json @@ -0,0 +1,19 @@ + +{ + "version": "2.0.0", + "tasks": [ + { + "label": "check contracts", + "group": "test", + "type": "shell", + "command": "clarinet check" + }, + { + "type": "npm", + "script": "test", + "group": "test", + "problemMatcher": [], + "label": "npm test" + } + ] +} diff --git a/Meme-Empire/Clarinet.toml b/Meme-Empire/Clarinet.toml new file mode 100644 index 0000000..cd1782a --- /dev/null +++ b/Meme-Empire/Clarinet.toml @@ -0,0 +1,23 @@ +[project] +name = 'Meme-Empire' +description = '' +authors = [] +telemetry = true +cache_dir = './.cache' +requirements = [] +[contracts.Stacks-Meme] +path = 'contracts/Stacks-Meme.clar' +clarity_version = 3 +epoch = 3.1 +[repl.analysis] +passes = ['check_checker'] + +[repl.analysis.check_checker] +strict = false +trusted_sender = false +trusted_caller = false +callee_filter = false + +[repl.remote_data] +enabled = false +api_url = 'https://api.hiro.so' diff --git a/Meme-Empire/README b/Meme-Empire/README new file mode 100644 index 0000000..f0c4062 --- /dev/null +++ b/Meme-Empire/README @@ -0,0 +1,203 @@ +# MemeCoin Empire + +A comprehensive community-driven memecoin platform built on the Stacks blockchain, featuring gamified interactions, meme battles, and a reputation-based reward system. + +## Features + +### Core Token Functionality +- **SIP-010 Compliant**: Fully compliant with the Stacks Improvement Proposal 010 fungible token standard +- **Secure Transfers**: Multi-layer validation for all token transfers +- **Mint & Burn**: Administrative controls for token supply management +- **Metadata Support**: Extensible token metadata system + +### Community Features +- **Meme Collections**: Users can create and manage personal meme collections (up to 10 memes per user) +- **Tipping System**: Reward excellent meme creators with tokens +- **Battle System**: Engage in gamified meme battles with other users +- **Reputation System**: Earn "meme power" through community participation +- **Verified Creators**: Special status for recognized meme creators + +### Administrative Controls +- **Pause/Unpause**: Emergency controls for contract operations +- **Minting Toggle**: Enable/disable new token creation +- **Airdrop Functionality**: Mass distribution for community building +- **Supply Management**: Maximum supply caps and circulation tracking + +## Token Details + +| Property | Value | +|----------|-------| +| **Name** | MemeCoin Empire | +| **Symbol** | MEME | +| **Decimals** | 6 | +| **Max Supply** | 1,000,000,000 MEME | +| **Max Memes per User** | 10 | +| **Meme Character Limit** | 280 characters | + +## Gamification Elements + +### Meme Power System +- **Base Creation Reward**: 10 power points per meme +- **Tip Sender Bonus**: 5 power points for tipping +- **Tip Recipient Bonus**: 15 power points for receiving tips +- **Battle Victory Reward**: 25 power points for winning battles +- **Token Transfer Bonus**: 1 power point per 1000 tokens received + +### Battle System +- Battles are determined by meme power + pseudo-randomness +- Winners receive the wager amount from losers +- Battle statistics are tracked for each user +- Victory grants additional meme power + +## Getting Started + +### Prerequisites +- [Clarinet](https://github.com/hirosystems/clarinet) - Stacks smart contract development tool +- [Node.js](https://nodejs.org/) - For running tests +- [Stacks Wallet](https://www.hiro.so/wallet) - For interacting with the contract + +### Installation + +1. **Clone the repository** + ```bash + git clone + cd memecoin-empire + ``` + +2. **Install dependencies** + ```bash + npm install + ``` + +3. **Check contract syntax** + ```bash + clarinet check + ``` + +4. **Run tests** + ```bash + npm test + ``` + +### Deployment + +1. **Deploy to testnet** + ```bash + clarinet integrate + ``` + +2. **Deploy to mainnet** + ```bash + clarinet deploy --network mainnet + ``` + +## Contract Functions + +### Public Functions + +#### Token Operations +- `transfer(amount, sender, recipient, memo)` - Transfer tokens between accounts +- `mint-tokens-to-address(amount, recipient)` - Mint new tokens (admin only) +- `burn-user-tokens(amount)` - Burn tokens from user's balance + +#### Meme Functions +- `submit-meme-to-collection(content)` - Add meme to personal collection +- `tip-meme-creator(creator, amount, meme)` - Tip a meme creator +- `initiate-meme-battle(opponent, wager)` - Start a meme battle + +#### Administrative Functions +- `initialize-memecoin-empire(allocation)` - Initialize contract with founder allocation +- `update-token-metadata-uri(uri)` - Update token metadata +- `toggle-minting-functionality()` - Enable/disable minting +- `toggle-contract-operations-pause()` - Pause/unpause contract +- `execute-community-airdrop(recipients, amount)` - Mass token distribution + +### Read-Only Functions + +#### Token Information +- `get-name()` - Returns token name +- `get-symbol()` - Returns token symbol +- `get-decimals()` - Returns decimal precision +- `get-balance(address)` - Returns user's token balance +- `get-total-supply()` - Returns total token supply +- `get-token-uri()` - Returns metadata URI + +#### User Information +- `get-user-meme-collection(address)` - Returns user's meme collection +- `get-user-meme-power(address)` - Returns user's meme power level +- `is-verified-meme-creator(address)` - Checks creator verification status +- `get-battle-statistics(address)` - Returns user's battle stats + +#### Contract Status +- `is-contract-paused()` - Returns pause status +- `is-minting-enabled()` - Returns minting status +- `get-contract-administrator()` - Returns admin address +- `get-complete-token-information()` - Returns comprehensive contract info + +## Security Features + +### Access Control +- Administrator-only functions protected by sender validation +- Self-interaction prevention for transfers and battles +- Comprehensive input validation on all functions + +### Economic Security +- Maximum supply enforcement +- Balance validation before transfers +- Wager validation for battles +- Minting controls with emergency pause + +### Error Handling +- Comprehensive error codes for different failure scenarios +- Graceful failure handling with descriptive error messages +- Transaction rollback on validation failures + +## Use Cases + +### For Users +- **Meme Creators**: Earn tokens and reputation by creating quality memes +- **Community Members**: Participate in battles, tip creators, build collections +- **Collectors**: Curate personal meme collections and build reputation +- **Traders**: Transfer and trade tokens with other community members + +### For Administrators +- **Community Building**: Use airdrops to grow the user base +- **Economic Management**: Control token supply and circulation +- **Emergency Response**: Pause operations if needed +- **Metadata Management**: Update token information as needed + +### Tokenomics + +### Token Distribution +- **Founder Allocation**: Set during contract initialization +- **Community Rewards**: Distributed through meme creation and battles +- **Airdrops**: Mass distribution for community growth +- **Tipping Economy**: Peer-to-peer rewards for quality content + +### Reward Structure +- **Content Creation**: Rewards for submitting memes +- **Community Engagement**: Bonuses for tipping and participating +- **Competitive Gaming**: Battle rewards based on skill and luck +- **Token Holding**: Meme power bonuses for token accumulation + +## Development + +### Contract Structure +``` +contracts/ +├── Stacks-Meme.clar # Main contract file +tests/ +├── memecoin-empire.test.ts # Test suite +├── helpers/ # Test utilities +settings/ +├── Clarinet.toml # Project configuration +├── Devnet.toml # Development network settings +``` + +### Testing +The contract includes comprehensive test coverage for: +- Token transfer functionality +- Meme creation and management +- Battle system mechanics +- Administrative functions +- Error handling scenarios \ No newline at end of file diff --git a/Meme-Empire/contracts/Stacks-Meme.clar b/Meme-Empire/contracts/Stacks-Meme.clar new file mode 100644 index 0000000..2e15330 --- /dev/null +++ b/Meme-Empire/contracts/Stacks-Meme.clar @@ -0,0 +1,420 @@ +;; MemeCoin Empire - Advanced Community-Driven Memecoin Platform +;; +;; This smart contract implements a comprehensive memecoin ecosystem with: +;; - Standard SIP-010 fungible token functionality +;; - Community meme creation and curation system +;; - Gamified battles and tipping mechanisms +;; - Reputation-based rewards and creator recognition +;; - Administrative controls for sustainable tokenomics + +;; TOKEN DEFINITION & METADATA +(define-fungible-token memecoin-empire-token) +;; ERROR CONSTANTS +;; Authorization Errors +(define-constant ERR-UNAUTHORIZED-ACCESS (err u100)) +(define-constant ERR-INSUFFICIENT-TOKEN-OWNERSHIP (err u101)) +(define-constant ERR-FORBIDDEN-SELF-INTERACTION (err u102)) + +;; Transaction Errors +(define-constant ERR-INADEQUATE-BALANCE (err u200)) +(define-constant ERR-INVALID-TRANSFER-AMOUNT (err u201)) +(define-constant ERR-TRANSFER-EXECUTION-FAILED (err u202)) +(define-constant ERR-INVALID-RECIPIENT-ADDRESS (err u203)) + +;; Contract State Errors +(define-constant ERR-CONTRACT-TEMPORARILY-PAUSED (err u300)) +(define-constant ERR-TOKEN-MINTING-DISABLED (err u301)) +(define-constant ERR-INITIAL-SUPPLY-ALREADY-MINTED (err u302)) +(define-constant ERR-MAXIMUM-SUPPLY-EXCEEDED (err u303)) + +;; Validation Errors +(define-constant ERR-INVALID-AMOUNT-PROVIDED (err u400)) +(define-constant ERR-MAXIMUM-MEME-LIMIT-REACHED (err u401)) +(define-constant ERR-INSUFFICIENT-MEME-POWER (err u402)) + +;; TOKEN CONFIGURATION CONSTANTS + +(define-constant contract-administrator tx-sender) +(define-constant memecoin-name "MemeCoin Empire") +(define-constant memecoin-symbol "MEME") +(define-constant token-decimal-precision u6) +(define-constant maximum-token-supply u1000000000000000) ;; 1 billion tokens with 6 decimals +(define-constant maximum-memes-per-user u10) +(define-constant meme-character-limit u280) +(define-constant base-meme-creation-reward u10) +(define-constant meme-tip-sender-bonus u5) +(define-constant meme-tip-recipient-bonus u15) +(define-constant battle-victory-reward u25) +(define-constant maximum-airdrop-recipients u100) + +;; CONTRACT STATE VARIABLES +(define-data-var token-metadata-uri (optional (string-utf8 256)) none) +(define-data-var is-minting-functionality-enabled bool true) +(define-data-var is-contract-operations-paused bool false) +(define-data-var current-circulating-supply uint u0) + +;; DATA STORAGE MAP + +;; Core token functionality +(define-map user-token-balances principal uint) +(define-map token-spending-allowances {token-owner: principal, authorized-spender: principal} uint) + +;; Meme ecosystem data +(define-map verified-meme-creators principal bool) +(define-map user-meme-power-levels principal uint) +(define-map user-meme-collections principal (list 10 (string-utf8 280))) +(define-map meme-battle-statistics principal {battles-won: uint, battles-participated: uint}) + +;; UTILITY & VALIDATION FUNCTIONS + +(define-private (validate-contract-administrator) + (is-eq tx-sender contract-administrator)) + +(define-private (validate-positive-amount (transaction-amount uint)) + (> transaction-amount u0)) + +(define-private (validate-contract-not-paused) + (not (var-get is-contract-operations-paused))) + +(define-private (retrieve-user-balance-or-zero (account-address principal)) + (default-to u0 (map-get? user-token-balances account-address))) + +(define-private (update-user-token-balance (account-address principal) (new-balance uint)) + (if (> new-balance u0) + (map-set user-token-balances account-address new-balance) + (map-delete user-token-balances account-address))) + +(define-private (calculate-meme-power-bonus (token-amount uint)) + (/ token-amount u1000)) + +(define-private (generate-pseudo-random-number (seed uint)) + (mod (+ (stacks-block-height) seed) u10)) + +;; SIP-010 STANDARD IMPLEMENTATION + +;; Primary token transfer function with comprehensive validation +(define-public (transfer (transfer-amount uint) + (sender-address principal) + (recipient-address principal) + (transaction-memo (optional (buff 34)))) + (begin + ;; Comprehensive input validation + (asserts! (validate-contract-not-paused) ERR-CONTRACT-TEMPORARILY-PAUSED) + (asserts! (validate-positive-amount transfer-amount) ERR-INVALID-AMOUNT-PROVIDED) + (asserts! (not (is-eq sender-address recipient-address)) ERR-FORBIDDEN-SELF-INTERACTION) + (asserts! (is-eq tx-sender sender-address) ERR-INSUFFICIENT-TOKEN-OWNERSHIP) + (asserts! (>= (retrieve-user-balance-or-zero sender-address) transfer-amount) ERR-INADEQUATE-BALANCE) + + ;; Execute core token transfer + (try! (ft-transfer? memecoin-empire-token transfer-amount sender-address recipient-address)) + + ;; Update user balance tracking + (let ((sender-new-balance (- (retrieve-user-balance-or-zero sender-address) transfer-amount)) + (recipient-new-balance (+ (retrieve-user-balance-or-zero recipient-address) transfer-amount))) + (update-user-token-balance sender-address sender-new-balance) + (update-user-token-balance recipient-address recipient-new-balance) + + ;; Award meme power to recipient based on tokens received + (let ((power-bonus (calculate-meme-power-bonus transfer-amount))) + (map-set user-meme-power-levels + recipient-address + (+ (default-to u0 (map-get? user-meme-power-levels recipient-address)) power-bonus))) + ) + + ;; Emit transfer event for blockchain indexers + (print { + event-type: "token-transfer", + from-address: sender-address, + to-address: recipient-address, + transferred-amount: transfer-amount, + transaction-memo: transaction-memo, + block-height: (stacks-block-height) + }) + + (ok true))) + +;; Token metadata retrieval functions +(define-read-only (get-name) + (ok memecoin-name)) + +(define-read-only (get-symbol) + (ok memecoin-symbol)) + +(define-read-only (get-decimals) + (ok token-decimal-precision)) + +(define-read-only (get-balance (account-address principal)) + (ok (ft-get-balance memecoin-empire-token account-address))) + +(define-read-only (get-total-supply) + (ok (ft-get-supply memecoin-empire-token))) + +(define-read-only (get-token-uri) + (ok (var-get token-metadata-uri))) + +;; ADMINISTRATIVE FUNCTIONS + +;; Mint new tokens with comprehensive validation +(define-public (mint-tokens-to-address (mint-amount uint) (recipient-address principal)) + (begin + (asserts! (validate-contract-administrator) ERR-UNAUTHORIZED-ACCESS) + (asserts! (var-get is-minting-functionality-enabled) ERR-TOKEN-MINTING-DISABLED) + (asserts! (validate-positive-amount mint-amount) ERR-INVALID-AMOUNT-PROVIDED) + (asserts! (<= (+ (ft-get-supply memecoin-empire-token) mint-amount) maximum-token-supply) + ERR-MAXIMUM-SUPPLY-EXCEEDED) + + ;; Execute minting operation + (try! (ft-mint? memecoin-empire-token mint-amount recipient-address)) + (update-user-token-balance recipient-address + (+ (retrieve-user-balance-or-zero recipient-address) mint-amount)) + (var-set current-circulating-supply (+ (var-get current-circulating-supply) mint-amount)) + + ;; Grant meme creator status to recipient + (map-set verified-meme-creators recipient-address true) + + (print { + event-type: "token-minting", + recipient-address: recipient-address, + minted-amount: mint-amount, + new-total-supply: (ft-get-supply memecoin-empire-token) + }) + + (ok true))) + +;; Burn tokens from user's balance +(define-public (burn-user-tokens (burn-amount uint)) + (begin + (asserts! (validate-contract-not-paused) ERR-CONTRACT-TEMPORARILY-PAUSED) + (asserts! (validate-positive-amount burn-amount) ERR-INVALID-AMOUNT-PROVIDED) + (asserts! (>= (retrieve-user-balance-or-zero tx-sender) burn-amount) ERR-INADEQUATE-BALANCE) + + (try! (ft-burn? memecoin-empire-token burn-amount tx-sender)) + (update-user-token-balance tx-sender (- (retrieve-user-balance-or-zero tx-sender) burn-amount)) + (var-set current-circulating-supply (- (var-get current-circulating-supply) burn-amount)) + + (print { + event-type: "token-burning", + burned-by: tx-sender, + burned-amount: burn-amount, + remaining-supply: (ft-get-supply memecoin-empire-token) + }) + + (ok true))) + +;; Update token metadata URI +(define-public (update-token-metadata-uri (new-metadata-uri (string-utf8 256))) + (begin + (asserts! (validate-contract-administrator) ERR-UNAUTHORIZED-ACCESS) + (var-set token-metadata-uri (some new-metadata-uri)) + (ok true))) + +;; Toggle minting functionality +(define-public (toggle-minting-functionality) + (begin + (asserts! (validate-contract-administrator) ERR-UNAUTHORIZED-ACCESS) + (var-set is-minting-functionality-enabled (not (var-get is-minting-functionality-enabled))) + (ok (var-get is-minting-functionality-enabled)))) + +;; Emergency pause/unpause contract operations +(define-public (toggle-contract-operations-pause) + (begin + (asserts! (validate-contract-administrator) ERR-UNAUTHORIZED-ACCESS) + (var-set is-contract-operations-paused (not (var-get is-contract-operations-paused))) + (ok (var-get is-contract-operations-paused)))) + +;; MEME ECOSYSTEM FUNCTIONS + +;; Add meme to user's personal collection +(define-public (submit-meme-to-collection (meme-content (string-utf8 280))) + (let ((user-current-memes (default-to (list) (map-get? user-meme-collections tx-sender))) + (current-meme-count (len user-current-memes))) + + (asserts! (> (ft-get-balance memecoin-empire-token tx-sender) u0) ERR-INADEQUATE-BALANCE) + (asserts! (< current-meme-count maximum-memes-per-user) ERR-MAXIMUM-MEME-LIMIT-REACHED) + + ;; Add meme to user's collection + (map-set user-meme-collections + tx-sender + (unwrap! (as-max-len? (append user-current-memes meme-content) u10) + ERR-MAXIMUM-MEME-LIMIT-REACHED)) + + ;; Reward user with meme power + (map-set user-meme-power-levels + tx-sender + (+ (default-to u0 (map-get? user-meme-power-levels tx-sender)) base-meme-creation-reward)) + + (print { + event-type: "meme-submission", + meme-creator: tx-sender, + meme-content: meme-content, + power-reward: base-meme-creation-reward, + total-user-memes: (+ current-meme-count u1) + }) + + (ok true))) + +;; Tip another user for excellent meme content +(define-public (tip-meme-creator (creator-address principal) + (tip-amount uint) + (appreciated-meme (string-utf8 280))) + (begin + (asserts! (validate-contract-not-paused) ERR-CONTRACT-TEMPORARILY-PAUSED) + (asserts! (validate-positive-amount tip-amount) ERR-INVALID-AMOUNT-PROVIDED) + (asserts! (not (is-eq tx-sender creator-address)) ERR-FORBIDDEN-SELF-INTERACTION) + (asserts! (>= (ft-get-balance memecoin-empire-token tx-sender) tip-amount) ERR-INADEQUATE-BALANCE) + + ;; Execute tip transfer + (try! (transfer tip-amount tx-sender creator-address none)) + + ;; Award bonus meme power to both parties + (map-set user-meme-power-levels + tx-sender + (+ (default-to u0 (map-get? user-meme-power-levels tx-sender)) meme-tip-sender-bonus)) + (map-set user-meme-power-levels + creator-address + (+ (default-to u0 (map-get? user-meme-power-levels creator-address)) meme-tip-recipient-bonus)) + + (print { + event-type: "meme-creator-tip", + tipper-address: tx-sender, + creator-address: creator-address, + tip-amount: tip-amount, + appreciated-meme: appreciated-meme + }) + + (ok true))) + +;; Engage in meme battle with another user +(define-public (initiate-meme-battle (opponent-address principal) (battle-wager uint)) + (begin + (asserts! (validate-contract-not-paused) ERR-CONTRACT-TEMPORARILY-PAUSED) + (asserts! (validate-positive-amount battle-wager) ERR-INVALID-AMOUNT-PROVIDED) + (asserts! (not (is-eq tx-sender opponent-address)) ERR-FORBIDDEN-SELF-INTERACTION) + (asserts! (>= (ft-get-balance memecoin-empire-token tx-sender) battle-wager) ERR-INADEQUATE-BALANCE) + (asserts! (>= (ft-get-balance memecoin-empire-token opponent-address) battle-wager) ERR-INADEQUATE-BALANCE) + + ;; Calculate battle outcome using meme power and randomness + (let ((initiator-power (default-to u0 (map-get? user-meme-power-levels tx-sender))) + (opponent-power (default-to u0 (map-get? user-meme-power-levels opponent-address))) + (random-factor (generate-pseudo-random-number (+ initiator-power opponent-power))) + (battle-winner (if (> (+ initiator-power random-factor) opponent-power) tx-sender opponent-address)) + (battle-loser (if (is-eq battle-winner tx-sender) opponent-address tx-sender))) + + ;; Transfer wager from loser to winner + (try! (transfer battle-wager battle-loser battle-winner none)) + + ;; Update battle statistics + (let ((winner-current-stats (default-to {battles-won: u0, battles-participated: u0} + (map-get? meme-battle-statistics battle-winner))) + (loser-current-stats (default-to {battles-won: u0, battles-participated: u0} + (map-get? meme-battle-statistics battle-loser)))) + + (map-set meme-battle-statistics battle-winner + {battles-won: (+ (get battles-won winner-current-stats) u1), + battles-participated: (+ (get battles-participated winner-current-stats) u1)}) + (map-set meme-battle-statistics battle-loser + {battles-won: (get battles-won loser-current-stats), + battles-participated: (+ (get battles-participated loser-current-stats) u1)}) + ) + + ;; Award victory meme power + (map-set user-meme-power-levels + battle-winner + (+ (default-to u0 (map-get? user-meme-power-levels battle-winner)) battle-victory-reward)) + + (print { + event-type: "meme-battle-completed", + battle-winner: battle-winner, + battle-loser: battle-loser, + wager-amount: battle-wager, + winner-final-power: (default-to u0 (map-get? user-meme-power-levels battle-winner)) + }) + + (ok battle-winner)))) + +;; Mass token distribution for community building +(define-public (execute-community-airdrop (recipient-list (list 100 principal)) (airdrop-amount uint)) + (begin + (asserts! (validate-contract-administrator) ERR-UNAUTHORIZED-ACCESS) + (asserts! (var-get is-minting-functionality-enabled) ERR-TOKEN-MINTING-DISABLED) + (asserts! (validate-positive-amount airdrop-amount) ERR-INVALID-AMOUNT-PROVIDED) + + (fold execute-individual-airdrop recipient-list (ok airdrop-amount)))) + +(define-private (execute-individual-airdrop (recipient-address principal) + (previous-result (response uint uint))) + (match previous-result + success-amount + (begin + (try! (mint-tokens-to-address success-amount recipient-address)) + (ok success-amount)) + error-code + (err error-code))) + +;; QUERY FUNCTIONS +;; Retrieve user's meme collection +(define-read-only (get-user-meme-collection (user-address principal)) + (default-to (list) (map-get? user-meme-collections user-address))) + +;; Get user's current meme power level +(define-read-only (get-user-meme-power (user-address principal)) + (default-to u0 (map-get? user-meme-power-levels user-address))) + +;; Check verified meme creator status +(define-read-only (is-verified-meme-creator (user-address principal)) + (default-to false (map-get? verified-meme-creators user-address))) + +;; Get user's battle statistics +(define-read-only (get-battle-statistics (user-address principal)) + (default-to {battles-won: u0, battles-participated: u0} + (map-get? meme-battle-statistics user-address))) + +;; Check if contract is paused +(define-read-only (is-contract-paused) + (var-get is-contract-operations-paused)) + +;; Check if minting is enabled +(define-read-only (is-minting-enabled) + (var-get is-minting-functionality-enabled)) + +;; Get contract administrator +(define-read-only (get-contract-administrator) + contract-administrator) + +;; Comprehensive token and contract information +(define-read-only (get-complete-token-information) + { + token-name: memecoin-name, + token-symbol: memecoin-symbol, + decimal-precision: token-decimal-precision, + current-supply: (ft-get-supply memecoin-empire-token), + maximum-supply: maximum-token-supply, + metadata-uri: (var-get token-metadata-uri), + minting-enabled: (var-get is-minting-functionality-enabled), + contract-paused: (var-get is-contract-operations-paused), + contract-administrator: contract-administrator + }) +;; CONTRACT INITIALIZATION +;; Initialize contract with founder allocation +(define-public (initialize-memecoin-empire (founder-allocation uint)) + (begin + (asserts! (validate-contract-administrator) ERR-UNAUTHORIZED-ACCESS) + (asserts! (is-eq (ft-get-supply memecoin-empire-token) u0) ERR-INITIAL-SUPPLY-ALREADY-MINTED) + (asserts! (<= founder-allocation maximum-token-supply) ERR-INVALID-AMOUNT-PROVIDED) + + ;; Mint initial supply to contract administrator + (try! (ft-mint? memecoin-empire-token founder-allocation contract-administrator)) + (update-user-token-balance contract-administrator founder-allocation) + (var-set current-circulating-supply founder-allocation) + + ;; Grant founder special status + (map-set verified-meme-creators contract-administrator true) + (map-set user-meme-power-levels contract-administrator u100) + + (print { + event-type: "contract-initialization", + founder-allocation: founder-allocation, + contract-administrator: contract-administrator + }) + + (ok true))) \ No newline at end of file diff --git a/Meme-Empire/package.json b/Meme-Empire/package.json new file mode 100644 index 0000000..095a60c --- /dev/null +++ b/Meme-Empire/package.json @@ -0,0 +1,23 @@ + +{ + "name": "Meme-Empire-tests", + "version": "1.0.0", + "description": "Run unit tests on this project.", + "type": "module", + "private": true, + "scripts": { + "test": "vitest run", + "test:report": "vitest run -- --coverage --costs", + "test:watch": "chokidar \"tests/**/*.ts\" \"contracts/**/*.clar\" -c \"npm run test:report\"" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@hirosystems/clarinet-sdk": "^3.0.2", + "@stacks/transactions": "^7.0.6", + "@types/node": "^22.15.18", + "chokidar-cli": "^3.0.0", + "vitest": "^3.1.3", + "vitest-environment-clarinet": "^2.3.0" + } +} diff --git a/Meme-Empire/settings/Devnet.toml b/Meme-Empire/settings/Devnet.toml new file mode 100644 index 0000000..f4f73ef --- /dev/null +++ b/Meme-Empire/settings/Devnet.toml @@ -0,0 +1,168 @@ +[network] +name = "devnet" +deployment_fee_rate = 10 + +[accounts.deployer] +mnemonic = "twice kind fence tip hidden tilt action fragile skin nothing glory cousin green tomorrow spring wrist shed math olympic multiply hip blue scout claw" +balance = 100_000_000_000_000 +sbtc_balance = 1_000_000_000 +# secret_key: 753b7cc01a1a2e86221266a154af739463fce51219d97e4f856cd7200c3bd2a601 +# stx_address: ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM +# btc_address: mqVnk6NPRdhntvfm4hh9vvjiRkFDUuSYsH + +[accounts.wallet_1] +mnemonic = "sell invite acquire kitten bamboo drastic jelly vivid peace spawn twice guilt pave pen trash pretty park cube fragile unaware remain midnight betray rebuild" +balance = 100_000_000_000_000 +sbtc_balance = 1_000_000_000 +# secret_key: 7287ba251d44a4d3fd9276c88ce34c5c52a038955511cccaf77e61068649c17801 +# stx_address: ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5 +# btc_address: mr1iPkD9N3RJZZxXRk7xF9d36gffa6exNC + +[accounts.wallet_2] +mnemonic = "hold excess usual excess ring elephant install account glad dry fragile donkey gaze humble truck breeze nation gasp vacuum limb head keep delay hospital" +balance = 100_000_000_000_000 +sbtc_balance = 1_000_000_000 +# secret_key: 530d9f61984c888536871c6573073bdfc0058896dc1adfe9a6a10dfacadc209101 +# stx_address: ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG +# btc_address: muYdXKmX9bByAueDe6KFfHd5Ff1gdN9ErG + +[accounts.wallet_3] +mnemonic = "cycle puppy glare enroll cost improve round trend wrist mushroom scorpion tower claim oppose clever elephant dinosaur eight problem before frozen dune wagon high" +balance = 100_000_000_000_000 +sbtc_balance = 1_000_000_000 +# secret_key: d655b2523bcd65e34889725c73064feb17ceb796831c0e111ba1a552b0f31b3901 +# stx_address: ST2JHG361ZXG51QTKY2NQCVBPPRRE2KZB1HR05NNC +# btc_address: mvZtbibDAAA3WLpY7zXXFqRa3T4XSknBX7 + +[accounts.wallet_4] +mnemonic = "board list obtain sugar hour worth raven scout denial thunder horse logic fury scorpion fold genuine phrase wealth news aim below celery when cabin" +balance = 100_000_000_000_000 +sbtc_balance = 1_000_000_000 +# secret_key: f9d7206a47f14d2870c163ebab4bf3e70d18f5d14ce1031f3902fbbc894fe4c701 +# stx_address: ST2NEB84ASENDXKYGJPQW86YXQCEFEX2ZQPG87ND +# btc_address: mg1C76bNTutiCDV3t9nWhZs3Dc8LzUufj8 + +[accounts.wallet_5] +mnemonic = "hurry aunt blame peanut heavy update captain human rice crime juice adult scale device promote vast project quiz unit note reform update climb purchase" +balance = 100_000_000_000_000 +sbtc_balance = 1_000_000_000 +# secret_key: 3eccc5dac8056590432db6a35d52b9896876a3d5cbdea53b72400bc9c2099fe801 +# stx_address: ST2REHHS5J3CERCRBEPMGH7921Q6PYKAADT7JP2VB +# btc_address: mweN5WVqadScHdA81aATSdcVr4B6dNokqx + +[accounts.wallet_6] +mnemonic = "area desk dutch sign gold cricket dawn toward giggle vibrant indoor bench warfare wagon number tiny universe sand talk dilemma pottery bone trap buddy" +balance = 100_000_000_000_000 +sbtc_balance = 1_000_000_000 +# secret_key: 7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01 +# stx_address: ST3AM1A56AK2C1XAFJ4115ZSV26EB49BVQ10MGCS0 +# btc_address: mzxXgV6e4BZSsz8zVHm3TmqbECt7mbuErt + +[accounts.wallet_7] +mnemonic = "prevent gallery kind limb income control noise together echo rival record wedding sense uncover school version force bleak nuclear include danger skirt enact arrow" +balance = 100_000_000_000_000 +sbtc_balance = 1_000_000_000 +# secret_key: b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401 +# stx_address: ST3PF13W7Z0RRM42A8VZRVFQ75SV1K26RXEP8YGKJ +# btc_address: n37mwmru2oaVosgfuvzBwgV2ysCQRrLko7 + +[accounts.wallet_8] +mnemonic = "female adjust gallery certain visit token during great side clown fitness like hurt clip knife warm bench start reunion globe detail dream depend fortune" +balance = 100_000_000_000_000 +sbtc_balance = 1_000_000_000 +# secret_key: 6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01 +# stx_address: ST3NBRSFKX28FQ2ZJ1MAKX58HKHSDGNV5N7R21XCP +# btc_address: n2v875jbJ4RjBnTjgbfikDfnwsDV5iUByw + +[accounts.faucet] +mnemonic = "shadow private easily thought say logic fault paddle word top book during ignore notable orange flight clock image wealth health outside kitten belt reform" +balance = 100_000_000_000_000 +sbtc_balance = 1_000_000_000 +# secret_key: de433bdfa14ec43aa1098d5be594c8ffb20a31485ff9de2923b2689471c401b801 +# stx_address: STNHKEPYEPJ8ET55ZZ0M5A34J0R3N5FM2CMMMAZ6 +# btc_address: mjSrB3wS4xab3kYqFktwBzfTdPg367ZJ2d + +[devnet] +disable_stacks_explorer = false +disable_stacks_api = false +# disable_postgres = false +# disable_subnet_api = false +# disable_bitcoin_explorer = true +# working_dir = "tmp/devnet" +# stacks_node_events_observers = ["host.docker.internal:8002"] +# miner_mnemonic = "fragile loan twenty basic net assault jazz absorb diet talk art shock innocent float punch travel gadget embrace caught blossom hockey surround initial reduce" +# miner_derivation_path = "m/44'/5757'/0'/0/0" +# faucet_mnemonic = "shadow private easily thought say logic fault paddle word top book during ignore notable orange flight clock image wealth health outside kitten belt reform" +# faucet_derivation_path = "m/44'/5757'/0'/0/0" +# stacker_mnemonic = "empty lens any direct brother then drop fury rule pole win claim scissors list rescue horn rent inform relief jump sword weekend half legend" +# stacker_derivation_path = "m/44'/5757'/0'/0/0" +# orchestrator_port = 20445 +# bitcoin_node_p2p_port = 18444 +# bitcoin_node_rpc_port = 18443 +# bitcoin_node_username = "devnet" +# bitcoin_node_password = "devnet" +# bitcoin_controller_block_time = 30_000 +# stacks_node_rpc_port = 20443 +# stacks_node_p2p_port = 20444 +# stacks_api_port = 3999 +# stacks_api_events_port = 3700 +# bitcoin_explorer_port = 8001 +# stacks_explorer_port = 8000 +# postgres_port = 5432 +# postgres_username = "postgres" +# postgres_password = "postgres" +# postgres_database = "postgres" +# bitcoin_node_image_url = "quay.io/hirosystems/bitcoind:26.0" +# stacks_node_image_url = "quay.io/hirosystems/stacks-node:devnet-3.1" +# stacks_signer_image_url = "quay.io/hirosystems/stacks-signer:devnet-3.1" +# stacks_api_image_url = "hirosystems/stacks-blockchain-api:master" +# stacks_explorer_image_url = "hirosystems/explorer:latest" +# bitcoin_explorer_image_url = "quay.io/hirosystems/bitcoin-explorer:devnet" +# postgres_image_url = "postgres:alpine" +# enable_subnet_node = true +# subnet_node_image_url = "hirosystems/stacks-subnets:0.8.1" +# subnet_leader_mnemonic = "twice kind fence tip hidden tilt action fragile skin nothing glory cousin green tomorrow spring wrist shed math olympic multiply hip blue scout claw" +# subnet_leader_derivation_path = "m/44'/5757'/0'/0/0" +# subnet_contract_id = "ST173JK7NZBA4BS05ZRATQH1K89YJMTGEH1Z5J52E.subnet-v3-0-1" +# subnet_node_rpc_port = 30443 +# subnet_node_p2p_port = 30444 +# subnet_events_ingestion_port = 30445 +# subnet_node_events_observers = ["host.docker.internal:8002"] +# subnet_api_image_url = "hirosystems/stacks-blockchain-api:master" +# subnet_api_postgres_database = "subnet_api" + +# epoch_2_0 = 100 +# epoch_2_05 = 100 +# epoch_2_1 = 101 +# epoch_2_2 = 102 +# epoch_2_3 = 103 +# epoch_2_4 = 104 +# epoch_2_5 = 108 +# epoch_3_0 = 142 +# epoch_3_1 = 144 + +# Send some stacking orders +[[devnet.pox_stacking_orders]] +start_at_cycle = 1 +duration = 10 +auto_extend = true +wallet = "wallet_1" +slots = 2 +btc_address = "mr1iPkD9N3RJZZxXRk7xF9d36gffa6exNC" + +[[devnet.pox_stacking_orders]] +start_at_cycle = 1 +duration = 10 +auto_extend = true +wallet = "wallet_2" +slots = 2 +btc_address = "muYdXKmX9bByAueDe6KFfHd5Ff1gdN9ErG" + +[[devnet.pox_stacking_orders]] +start_at_cycle = 1 +duration = 10 +auto_extend = true +wallet = "wallet_3" +slots = 2 +btc_address = "mvZtbibDAAA3WLpY7zXXFqRa3T4XSknBX7" + diff --git a/Meme-Empire/tests/Stacks-Meme.test.ts b/Meme-Empire/tests/Stacks-Meme.test.ts new file mode 100644 index 0000000..1f878ea --- /dev/null +++ b/Meme-Empire/tests/Stacks-Meme.test.ts @@ -0,0 +1,21 @@ + +import { describe, expect, it } from "vitest"; + +const accounts = simnet.getAccounts(); +const address1 = accounts.get("wallet_1")!; + +/* + The test below is an example. To learn more, read the testing documentation here: + https://docs.hiro.so/stacks/clarinet-js-sdk +*/ + +describe("example tests", () => { + it("ensures simnet is well initialised", () => { + expect(simnet.blockHeight).toBeDefined(); + }); + + // it("shows an example", () => { + // const { result } = simnet.callReadOnlyFn("counter", "get-counter", [], address1); + // expect(result).toBeUint(0); + // }); +}); diff --git a/Meme-Empire/tsconfig.json b/Meme-Empire/tsconfig.json new file mode 100644 index 0000000..1bdaf36 --- /dev/null +++ b/Meme-Empire/tsconfig.json @@ -0,0 +1,26 @@ + +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ESNext"], + "skipLibCheck": true, + + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + + "strict": true, + "noImplicitAny": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": [ + "node_modules/@hirosystems/clarinet-sdk/vitest-helpers/src", + "tests" + ] +} diff --git a/Meme-Empire/vitest.config.js b/Meme-Empire/vitest.config.js new file mode 100644 index 0000000..c6a8506 --- /dev/null +++ b/Meme-Empire/vitest.config.js @@ -0,0 +1,42 @@ + +/// + +import { defineConfig } from "vite"; +import { vitestSetupFilePath, getClarinetVitestsArgv } from "@hirosystems/clarinet-sdk/vitest"; + +/* + In this file, Vitest is configured so that it works seamlessly with Clarinet and the Simnet. + + The `vitest-environment-clarinet` will initialise the clarinet-sdk + and make the `simnet` object available globally in the test files. + + `vitestSetupFilePath` points to a file in the `@hirosystems/clarinet-sdk` package that does two things: + - run `before` hooks to initialize the simnet and `after` hooks to collect costs and coverage reports. + - load custom vitest matchers to work with Clarity values (such as `expect(...).toBeUint()`) + + The `getClarinetVitestsArgv()` will parse options passed to the command `vitest run --` + - vitest run -- --manifest ./Clarinet.toml # pass a custom path + - vitest run -- --coverage --costs # collect coverage and cost reports +*/ + +export default defineConfig({ + test: { + environment: "clarinet", // use vitest-environment-clarinet + pool: "forks", + poolOptions: { + threads: { singleThread: true }, + forks: { singleFork: true }, + }, + setupFiles: [ + vitestSetupFilePath, + // custom setup files can be added here + ], + environmentOptions: { + clarinet: { + ...getClarinetVitestsArgv(), + // add or override options + }, + }, + }, +}); +