UNPKG

@imaginarylabs/assemble

Version:

Assemble Protocol - Decentralized event management smart contracts with social coordination features

727 lines (592 loc) 26.7 kB
# Assemble Protocol A next-generation singleton smart contract protocol for onchain event management with comprehensive social coordination, location tracking, and multi-currency support. *Built with ERC-6909 multi-token standard, EIP-1153 transient storage, soulbound credentials, and advanced venue management.* ## Features ### Core Event Management - **Multi-Tier Ticketing** - Configurable pricing, capacity limits, and payment splits - **Location Integration** - GPS coordinate storage with efficient data packing - **Venue Credential System** - Soulbound tokens for organizers with venue experience - **Multi-Currency Support** - ETH and ERC20 token payments (USDC, DAI, etc.) - **Advanced Refund System** - Automatic refunds for cancelled events with 90-day claim window ### Privacy & Access Control - **Private Events** - Invite-only events with curated guest lists - **Flexible Visibility** - Public, private, and invite-only event types - **Social Graph** - Friends, RSVPs, and social discovery with onchain coordination - **Group Check-ins** - Delegate check-in functionality for group ticket purchases ### Advanced Payment Features - **Platform Fees** - Optional 0-5% referral fees to incentivize ecosystem growth - **ERC20 Payments** - Support for stablecoins and major tokens - **Payment Splits** - Automatic revenue distribution to multiple recipients - **Pull Payment Pattern** - Secure fund distribution with withdrawal mechanism ### Venue & Location System - **GPS Coordinate Storage** - Precise location data with efficient packing - **Venue Hash System** - Efficient venue identification and tracking - **Venue Credentials** - Soulbound reputation tokens for experienced organizers - **Location-Based Discovery** - Events searchable by geographic location ### Token & Badge System - **ERC-6909 Multi-Token** - Efficient batch operations for tickets and badges - **Transferrable Tickets** - Standard event tickets with resale capability - **Soulbound Badges** - Non-transferable attendance and organizer credentials - **Venue Credentials** - Permanent reputation tokens for venue organizers ### Social Features - **Comment System** - Threaded event discussions with moderation controls - **RSVP Tracking** - Social commitment and attendance prediction - **Friend Network** - Social connections for event discovery - **Social Verification** - Reputation building through attendance history ## Architecture **Singleton Design** - Single contract manages all events, users, and social interactions **Multi-Token Standard** - ERC-6909 enables efficient batch operations for tickets and badges **Gas Optimization** - EIP-1153 transient storage reduces gas costs for complex operations **Soulbound Credentials** - Non-transferable tokens for attendance proof and organizer reputation **Location Integration** - GPS coordinates packed efficiently in 128-bit storage **Multi-Currency** - Native ETH and ERC20 token support with unified payment handling ### Token Types - `EVENT_TICKET` - Transferrable tickets for event access - `ATTENDANCE_BADGE` - Soulbound proof of attendance (ERC-5192) - `ORGANIZER_CRED` - Soulbound reputation tokens for event organizers - `VENUE_CRED` - Soulbound venue management credentials ### Event Visibility Levels - `PUBLIC` - Open to all users with full visibility - `PRIVATE` - Limited visibility, discoverable but restricted - `INVITE_ONLY` - Curated guest list with strict access control ### Payment Methods - **ETH** - Native Ethereum payments - **ERC20 Tokens** - USDC, DAI, and other standard tokens - **Mixed Payments** - Tips in ETH, tickets in ERC20 (or vice versa) ## Quick Start ### Install Dependencies ```bash forge install ``` ### Run Tests ```bash # Run all tests (196 tests) forge test # Run with gas reporting forge test --gas-report # Run specific test suites forge test --match-contract "LocationSystem" forge test --match-contract "ERC20Payment" forge test --match-contract "VenueSystem" ``` ### Deploy Locally ```bash # Start local testnet anvil # Deploy contracts for local testing (see test files for examples) forge test ``` ## Contract API ### Core Event Functions ```solidity // Create event with location data function createEvent( EventParams calldata params, TicketTier[] calldata tiers, PaymentSplit[] calldata splits ) external returns (uint256 eventId) ``` ### Ticket Purchase Functions ```solidity // ETH payments function purchaseTickets(uint256 eventId, uint256 tierId, uint256 quantity) external payable function purchaseTickets(uint256 eventId, uint256 tierId, uint256 quantity, address referrer, uint256 platformFeeBps) external payable // ERC20 payments function purchaseTicketsERC20(uint256 eventId, uint256 tierId, uint256 quantity, address token) external function purchaseTicketsERC20(uint256 eventId, uint256 tierId, uint256 quantity, address token, address referrer, uint256 platformFeeBps) external ``` ### ERC20 Payment Functions ```solidity // Tip events with ERC20 tokens function tipEventERC20(uint256 eventId, address token, uint256 amount) external function tipEventERC20(uint256 eventId, address token, uint256 amount, address referrer, uint256 platformFeeBps) external // Withdraw ERC20 earnings function claimERC20Funds(address token) external // Check token support function setSupportedToken(address token, bool supported) external ``` ### Social Functions ```solidity function addFriend(address friend) external function updateRSVP(uint256 eventId, RSVPStatus status) external function postComment(uint256 eventId, string calldata content, uint256 parentId) external ``` ### Private Event Functions ```solidity function inviteToEvent(uint256 eventId, address[] calldata invitees) external function isInvited(uint256 eventId, address user) external view returns (bool) ``` ## Token ID Structure (ERC-6909) ``` ┌─────────────┬─────────────┬─────────────┬─────────────┬─────────────┐ │ TokenType │ EventId │ TierId │ SerialNum │ Metadata │ │ (8 bits) │ (64 bits) │ (32 bits) │ (64 bits) │ (88 bits) │ └─────────────┴─────────────┴─────────────┴─────────────┴─────────────┘ ``` Single uint256 encodes token type, event reference, tier information, and unique serial number. ## Location System Precise GPS coordinate storage with efficient data packing: ```solidity // Create event with NYC coordinates (40.7431° N, 73.9597° W) int64 latitude = 40743100; // 40.7431 * 1e6 int64 longitude = -73959700; // -73.9597 * 1e6 uint256 eventId = assemble.createEvent{value: PLATFORM_FEE}( params, // includes latitude/longitude tiers, splits ); // Location data is automatically packed and stored efficiently ``` **Key Features:** - **Precision**: 6 decimal places (±1 meter accuracy) - **Efficient Storage**: 128-bit packed coordinates - **Global Coverage**: Full latitude/longitude range support - **Integration Ready**: Compatible with mapping APIs and services ## Venue Credential System Organizers earn soulbound venue credentials for hosting events: ```solidity // Create event at specific venue uint256 eventId = assemble.createEvent{value: PLATFORM_FEE}( params, // includes venueName: "The Fillmore" tiers, splits ); // Organizer automatically receives venue credential token (soulbound, non-transferable) // Venue credentials accumulate over time and build reputation ``` **Benefits:** - **Reputation Building** - Permanent record of venue management experience - **Trust Signals** - Visible proof of successful event history - **Venue Partnerships** - Credentials can unlock venue-specific benefits - **Anti-Fraud** - Prevents false venue claims and credential farming ## Multi-Currency Payments Support for ETH and major ERC20 tokens: ```solidity // USDC ticket purchase IERC20(USDC).approve(address(assemble), ticketPrice); assemble.purchaseTicketsERC20(eventId, tierId, quantity, USDC); // DAI event tip with platform fee IERC20(DAI).approve(address(assemble), tipAmount); assemble.tipEventERC20(eventId, DAI, tipAmount, platformAddress, 200); // Mixed payments - ETH tips, USDC tickets assemble.tipEvent{value: 0.01 ether}(eventId); assemble.purchaseTicketsERC20(eventId, 0, 1, USDC); ``` **Supported Tokens:** - **ETH** - Native Ethereum - **USDC** - USD Coin stablecoin - **DAI** - Dai stablecoin - **Any ERC20** - Standard token interface support **Features:** - **Pull Payment Pattern** - Secure withdrawal mechanism - **Mixed Currency Events** - Accept both ETH and ERC20 - **Platform Fee Support** - Platform fees work with all currencies - **Automatic Splitting** - Revenue splits work across all payment types ## Private Events Perfect for exclusive gatherings, private parties, corporate events, and curated experiences: ```solidity // Create invite-only event with location EventParams memory params = EventParams({ organizer: msg.sender, startTime: block.timestamp + 3600, venueName: "Private Residence", visibility: EventVisibility.INVITE_ONLY, // ... other params including GPS coordinates }); uint256 eventId = assemble.createEvent{value: PLATFORM_FEE}( params, tiers, splits ); // Invite specific guests address[] memory guests = [alice, bob, charlie]; assemble.inviteToEvent(eventId, guests); // Only invited users can see and purchase tickets ``` **Use Cases:** - **Wedding Celebrations** - Guest list management with location sharing - **Exclusive Art Openings** - Curated audience with venue credentials - **Corporate Retreats** - Private events with expense tracking - **VIP Product Launches** - Controlled access with social verification - **Community Gatherings** - Intimate events with reputation requirements ## Platform Fees & Ecosystem Incentives Platform fees (0-5%) enable sustainable ecosystem growth: ```solidity // Music venue gets 2% for hosting (ETH) assemble.purchaseTickets{value: ticketPrice}(eventId, 0, 1, venueAddress, 200); // Event platform gets 1.5% for promotion (USDC) assemble.purchaseTicketsERC20(eventId, 0, 1, USDC, platformAddress, 150); // Cross-currency platform fees work seamlessly assemble.tipEventERC20(eventId, DAI, tipAmount, influencerAddress, 100); ``` **Ecosystem Participants:** - **Music Venues** - Earn fees for hosting and promotion - **Event Platforms** - Monetize discovery and booking services - **Influencer Partners** - Revenue sharing for audience development - **Corporate Sponsors** - Track ROI on event investments - **Community Builders** - Sustain long-term community operations - **Venue Partners** - Leverage credentials for preferential rates ## Error Handling & User Experience Consolidated error handling for better UX: ```solidity // Consolidated error system error SocialError(); // Social interaction failures error PaymentError(); // Payment and financial failures error EventError(); // Event management failures error AccessError(); // Permission and access failures error ValidationError(); // Input validation failures ``` **Benefits:** - **Smaller Contract Size** - Consolidated errors reduce bytecode - **Better DX** - Consistent error patterns across functions - **Gas Efficiency** - Reduced deployment and execution costs - **Frontend Integration** - Easier error handling in applications ## Security & Testing ### Comprehensive Test Suite (196 Tests - 100% Pass Rate) - **Core Functionality** - 40+ tests covering all primary features - **Security Tests** - 17 tests for attack vectors and edge cases - **Edge Case Tests** - 22 tests for boundary conditions - **Fuzz Tests** - 15 property-based tests (1000 runs each) - **Invariant Tests** - 8 stateful tests (256 runs each) - **Scenario Tests** - 25 real-world usage patterns - **Private Event Tests** - 12 access control and privacy tests - **Location Tests** - 10 GPS and venue system tests - **ERC20 Payment Tests** - 15 multi-currency transaction tests ### Security Features - **Static Analysis Clean** - Zero issues with Slither - **EIP-1153 Reentrancy Protection** - Transient storage guards - **Pull Payment Pattern** - Secure fund distribution - **Soulbound Token Enforcement** - Prevents credential transfer - **Access Control** - Role-based permissions throughout - **Input Validation** - Comprehensive parameter checking - **Integer Overflow Protection** - SafeMath patterns where needed ### Gas Optimization - **Contract Size**: 24,214 bytes (under 24,576 limit) - **EIP-1153 Transient Storage** - Reduced state storage costs - **Efficient Data Packing** - Optimized struct layouts - **Batch Operations** - ERC-6909 multi-token efficiency - **View Function Optimization** - Direct mapping access patterns **This protocol has not been audited. Use at your own risk.** ## Gas Usage | Operation | ETH Gas | ERC20 Gas | |-----------|---------|-----------| | Create Event | 391,143 | N/A | | Create Event + Location | 398,180 | N/A | | Purchase Tickets | 153,928 | 195,440 | | Purchase with Platform Fee | ~165,000 | ~210,000 | | Private Event Invitations | 71,758 | N/A | | Check-in Operations | 69,378 - 82,124 | N/A | | Social Operations (RSVP/Friends) | 24,243 - 78,604 | N/A | | ERC20 Tips | N/A | 117,041 | | ERC20 Withdrawals | N/A | 53,918 | | Location Queries | 12,545 | N/A | *Note: Gas usage measured on latest protocol version. Actual usage may vary based on transaction complexity, network conditions, and specific parameters used.* ## Integration Examples ### Frontend Integration ```javascript import { keccak256, toBytes } from 'viem'; import { publicClient, walletClient } from './config'; // your viem client setup // Create event (NO ETH VALUE REQUIRED - creation is free) const tx = await walletClient.writeContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'createEvent', args: [params, ticketTiers, paymentSplits] // params includes latitude/longitude // NO value parameter - event creation is free! }); // Purchase tickets with USDC (platform fee charged here, not creation) await walletClient.writeContract({ address: USDC_ADDRESS, abi: erc20Abi, functionName: 'approve', args: [ASSEMBLE_ADDRESS, ticketPrice] }); await walletClient.writeContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'purchaseTicketsERC20', args: [eventId, tierId, quantity, USDC_ADDRESS] }); // Purchase with platform fee (2% to venue partner) await walletClient.writeContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'purchaseTickets', args: [eventId, tierId, quantity, venuePartnerAddress, 200], // 200 = 2% value: ticketPrice }); // Check venue credentials const venueHash = keccak256(toBytes(venueName)); const credTokenId = await publicClient.readContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'generateTokenId', args: [4, 0, venueHash, 0] // TokenType.VENUE_CRED = 4 }); const hasCredential = await publicClient.readContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'balanceOf', args: [organizer, credTokenId] }); ``` ### API Integration ```javascript import { keccak256, toBytes } from 'viem'; import { publicClient } from './config'; // Location-based event discovery const events = await fetchEventsNearLocation(latitude, longitude, radiusKm); // Multi-currency price display const prices = { eth: await publicClient.readContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'calculatePrice', args: [eventId, tierId, quantity] }), usdc: await getUSDCPrice(eventId, tierId, quantity), dai: await getDAIPrice(eventId, tierId, quantity) }; // Venue reputation display const venueHash = keccak256(toBytes(venueName)); const venueStats = { eventCount: await publicClient.readContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'venueEventCount', args: [venueHash] }), hasCredential: await publicClient.readContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'balanceOf', args: [organizer, credTokenId] }) > 0 }; ``` ## Fee Structure ### **Protocol Fees (Fixed)** - **Rate**: 0.5% (50 basis points) by default, maximum 10% - **Charged On**: All ticket purchases and tips - **Goes To**: Protocol treasury (`feeTo` address) - **Purpose**: Protocol maintenance and development ### **Platform Fees (Optional)** - **Rate**: 0-5% (0-500 basis points) - set per transaction - **Charged On**: Ticket purchases and tips (when specified) - **Goes To**: Referrer/platform address specified in transaction - **Purpose**: Ecosystem growth, venue partnerships, influencer rewards ## Fee Examples & Calculations ### **Example 1: Basic Ticket Purchase (Protocol Fee Only)** ```javascript // User buys 1 ticket for 0.1 ETH - NO platform fee await walletClient.writeContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'purchaseTickets', args: [eventId, 0, 1], // No referrer, no platform fee value: parseEther('0.1') // 0.1 ETH }); // Fee calculation: // Ticket price: 0.1 ETH // Protocol fee: 0.1 ETH × 0.5% = 0.0005 ETH (goes to protocol) // Net to organizer: 0.1 ETH - 0.0005 ETH = 0.0995 ETH ``` ### **Example 2: Ticket Purchase with Platform Fee** ```javascript // User buys 1 ticket for 0.1 ETH with 2% platform fee to venue partner await walletClient.writeContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'purchaseTickets', args: [eventId, 0, 1, venuePartnerAddress, 200], // 200 = 2% platform fee value: parseEther('0.1') }); // Fee calculation (order: Platform fee → Protocol fee → Event splits): // 1. Ticket price: 0.1 ETH // 2. Platform fee: 0.1 ETH × 2% = 0.002 ETH (goes to venue partner) // 3. Remaining: 0.1 ETH - 0.002 ETH = 0.098 ETH // 4. Protocol fee: 0.098 ETH × 0.5% = 0.00049 ETH (goes to protocol) // 5. Net to organizer: 0.098 ETH - 0.00049 ETH = 0.09751 ETH ``` ### **Example 3: Event Tip with Platform Fee** ```javascript // User tips 0.05 ETH with 1.5% platform fee to influencer await walletClient.writeContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'tipEvent', args: [eventId, influencerAddress, 150], // 150 = 1.5% platform fee value: parseEther('0.05') }); // Fee calculation: // 1. Tip amount: 0.05 ETH // 2. Platform fee: 0.05 ETH × 1.5% = 0.00075 ETH (goes to influencer) // 3. Remaining: 0.05 ETH - 0.00075 ETH = 0.04925 ETH // 4. Protocol fee: 0.04925 ETH × 0.5% = 0.00024625 ETH (goes to protocol) // 5. Net to event splits: 0.04925 ETH - 0.00024625 ETH = 0.04900375 ETH ``` ### **Example 4: ERC20 Payment with Platform Fee** ```javascript // User buys ticket with 100 USDC + 3% platform fee to venue await erc20Contract.writeContract({ functionName: 'approve', args: [ASSEMBLE_ADDRESS, parseUnits('100', 6)] // USDC has 6 decimals }); await walletClient.writeContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'purchaseTicketsERC20', args: [eventId, 0, 1, USDC_ADDRESS, venueAddress, 300] // 300 = 3% }); // Fee calculation (USDC amounts): // 1. Ticket price: 100 USDC // 2. Platform fee: 100 USDC × 3% = 3 USDC (goes to venue) // 3. Remaining: 100 USDC - 3 USDC = 97 USDC // 4. Protocol fee: 97 USDC × 0.5% = 0.485 USDC (goes to protocol) // 5. Net to organizer: 97 USDC - 0.485 USDC = 96.515 USDC ``` ### **Example 5: Multi-Split Event Revenue** ```javascript // Event with payment splits: 60% organizer, 30% artist, 10% venue const paymentSplits = [ { recipient: organizerAddress, bps: 6000 }, // 60% { recipient: artistAddress, bps: 3000 }, // 30% { recipient: venueAddress, bps: 1000 } // 10% ]; // User tips 1 ETH with 2% platform fee to promoter await walletClient.writeContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'tipEvent', args: [eventId, promoterAddress, 200], // 200 = 2% value: parseEther('1.0') }); // Fee calculation & distribution: // 1. Tip amount: 1.0 ETH // 2. Platform fee: 1.0 ETH × 2% = 0.02 ETH → promoterAddress // 3. Remaining: 1.0 ETH - 0.02 ETH = 0.98 ETH // 4. Protocol fee: 0.98 ETH × 0.5% = 0.0049 ETH → protocol treasury // 5. Net for splits: 0.98 ETH - 0.0049 ETH = 0.9751 ETH // 6. Distribution: // - Organizer: 0.9751 ETH × 60% = 0.58506 ETH // - Artist: 0.9751 ETH × 30% = 0.29253 ETH // - Venue: 0.9751 ETH × 10% = 0.09751 ETH ``` ### **Example 6: Platform Fee for Ecosystem Partners** ```javascript // Music venue gets 2% for hosting/promoting await walletClient.writeContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'purchaseTickets', args: [eventId, 0, 2, musicVenueAddress, 200], // 2 tickets, 2% to venue value: parseEther('0.2') // 0.1 ETH per ticket }); // Event discovery platform gets 1% for driving traffic await walletClient.writeContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'tipEvent', args: [eventId, eventPlatformAddress, 100], // 1% to platform value: parseEther('0.1') }); // Social media influencer gets 2.5% for promotion await walletClient.writeContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'purchaseTickets', args: [eventId, 1, 1, influencerAddress, 250], // 2.5% to influencer value: parseEther('0.15') }); ``` ### **Reading Fee Information** ```javascript // Check current protocol fee rate const protocolFeeBps = await publicClient.readContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'protocolFeeBps' }); console.log(`Protocol fee: ${protocolFeeBps / 100}%`); // e.g., "Protocol fee: 0.5%" // Check pending withdrawals (includes fees received) const pendingFees = await publicClient.readContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'pendingWithdrawals', args: [feeRecipientAddress] }); // Check ERC20 fees pending const pendingUSDC = await publicClient.readContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'pendingERC20Withdrawals', args: [USDC_ADDRESS, feeRecipientAddress] }); ``` ### **Event Cancellation & Refunds** - **Creation Cost**: ✅ **FREE** - No fees to create events - **Cancellation**: Events can be cancelled before start time - **Refund Window**: 90 days after cancellation - **Full Refunds**: Users get back exactly what they paid for tickets/tips - **Protocol Fees**: Not refunded (already used for infrastructure) - **Platform Fees**: Not refunded (already paid to referrers) ```javascript // Example: Event cancelled, user gets refund // User originally paid: 0.1 ETH for ticket // Platform fee: 0.002 ETH (already paid to venue partner - not refunded) // Protocol fee: 0.00049 ETH (already paid to protocol - not refunded) // User refund: 0.1 ETH (full original ticket price returned) await walletClient.writeContract({ address: ASSEMBLE_ADDRESS, abi: assembleAbi, functionName: 'claimTicketRefund', args: [cancelledEventId] }); // User receives back: 0.1 ETH (their full ticket payment) ``` ## Deployment ### Live Deployments Assemble Protocol is deployed with **identical vanity addresses** across 8 networks: **Mainnet (Chain ID: 1):** - **Assemble**: `0x000000000a020d45fFc5cfcF7B28B5020ddd6a85` ✅ [Verified](https://etherscan.io/address/0x000000000a020d45fFc5cfcF7B28B5020ddd6a85) - **SocialLibrary**: `0xebE033f26d5CAb84F5C174C882e2e036F59FAD55` ✅ [Verified](https://etherscan.io/address/0xebE033f26d5CAb84F5C174C882e2e036F59FAD55) **Sepolia Testnet (Chain ID: 11155111):** - **Assemble**: `0x000000000a020d45fFc5cfcF7B28B5020ddd6a85` ✅ [Verified](https://sepolia.etherscan.io/address/0x000000000a020d45fFc5cfcF7B28B5020ddd6a85) - **SocialLibrary**: `0xebE033f26d5CAb84F5C174C882e2e036F59FAD55` ✅ [Verified](https://sepolia.etherscan.io/address/0xebE033f26d5CAb84F5C174C882e2e036F59FAD55) **Base Mainnet (Chain ID: 8453):** - **Assemble**: `0x000000000a020d45fFc5cfcF7B28B5020ddd6a85` ✅ [Verified](https://basescan.org/address/0x000000000a020d45fFc5cfcF7B28B5020ddd6a85) - **SocialLibrary**: `0xebE033f26d5CAb84F5C174C882e2e036F59FAD55` ✅ [Verified](https://basescan.org/address/0xebE033f26d5CAb84F5C174C882e2e036F59FAD55) **Base Sepolia (Chain ID: 84532):** - **Assemble**: `0x000000000a020d45fFc5cfcF7B28B5020ddd6a85` ✅ [Verified](https://sepolia.basescan.org/address/0x000000000a020d45fFc5cfcF7B28B5020ddd6a85) - **SocialLibrary**: `0xebE033f26d5CAb84F5C174C882e2e036F59FAD55` ✅ [Verified](https://sepolia.basescan.org/address/0xebE033f26d5CAb84F5C174C882e2e036F59FAD55) **Optimism (Chain ID: 10):** - **Assemble**: `0x000000000a020d45fFc5cfcF7B28B5020ddd6a85` ✅ [Verified](https://optimistic.etherscan.io/address/0x000000000a020d45fFc5cfcF7B28B5020ddd6a85) - **SocialLibrary**: `0xebE033f26d5CAb84F5C174C882e2e036F59FAD55` ✅ [Verified](https://optimistic.etherscan.io/address/0xebE033f26d5CAb84F5C174C882e2e036F59FAD55) **Arbitrum One (Chain ID: 42161):** - **Assemble**: `0x000000000a020d45fFc5cfcF7B28B5020ddd6a85` ✅ [Verified](https://arbiscan.io/address/0x000000000a020d45fFc5cfcF7B28B5020ddd6a85) - **SocialLibrary**: `0xebE033f26d5CAb84F5C174C882e2e036F59FAD55` ✅ [Verified](https://arbiscan.io/address/0xebE033f26d5CAb84F5C174C882e2e036F59FAD55) **Polygon (Chain ID: 137):** - **Assemble**: `0x000000000a020d45fFc5cfcF7B28B5020ddd6a85` ✅ [Deployed](https://polygonscan.com/address/0x000000000a020d45fFc5cfcF7B28B5020ddd6a85) * - **SocialLibrary**: `0xebE033f26d5CAb84F5C174C882e2e036F59FAD55` ✅ [Deployed](https://polygonscan.com/address/0xebE033f26d5CAb84F5C174C882e2e036F59FAD55) * **Zora (Chain ID: 7777777):** - **Assemble**: `0x000000000a020d45fFc5cfcF7B28B5020ddd6a85` ✅ [Verified](https://explorer.zora.energy/address/0x000000000a020d45fFc5cfcF7B28B5020ddd6a85) - **SocialLibrary**: `0xebE033f26d5CAb84F5C174C882e2e036F59FAD55` ✅ [Verified](https://explorer.zora.energy/address/0xebE033f26d5CAb84F5C174C882e2e036F59FAD55) *\* Verification failed due to foundry bug #3507 with via_ir compiler setting on PolygonScan* ### Development Setup ```bash # Clone repository git clone https://github.com/your-org/assemble-protocol cd assemble-protocol # Install dependencies forge install # Run tests forge test # Run coverage forge coverage # Deploy locally anvil & forge test ``` ## License MIT License - see [LICENSE](./LICENSE) for details. --- **Built with love for the onchain event ecosystem** *Assemble Protocol - Where events meet the future of web3*