Documentation Index Fetch the complete documentation index at: https://docs.vibesflow.ai/llms.txt
Use this file to discover all available pages before exploring further.
PPM Contract
The Pay-Per-Minute (PPM) contract manages tMETIS allowances and automatic withdrawals for group vibestreams with real-time pricing. Each allowance is tied to a specific vibeID to ensure isolated spending authorization.
Contract Overview
Standard : Custom payment processing contract
Features : Time-based payments, allowance management, automatic distribution
Security : Reentrancy protection, emergency controls, pausable operations
Core Concepts
Participant Allowances
Each participant’s spending authorization is tracked per vibestream:
struct ParticipantAllowance {
uint256 vibeId; // The vibestream ID
address participant; // Participant's address
uint256 authorizedAmount; // Total authorized spending (wei)
uint256 spentAmount; // Amount already spent (wei)
uint256 payPerMinute; // Rate per minute (wei)
uint256 joinedAt; // Join timestamp
uint256 lastDeduction; // Last payment timestamp
bool isActive; // Currently streaming
address creator; // Vibestream creator
}
Vibestream Configuration
Each registered vibestream has associated configuration:
struct VibestreamConfig {
uint256 vibeId; // Vibestream identifier
address creator; // Creator address
uint256 payPerMinute; // Payment rate (wei per minute)
bool isActive; // Registration status
uint256 totalParticipants; // Active participant count
uint256 totalRevenue; // Cumulative revenue
}
Payment Flow
1. Vibestream Registration
Only the VibeFactory can register vibestreams:
function registerVibestream (
uint256 vibeId ,
address creator ,
uint256 payPerMinute
) external override onlyVibeFactory
2. Spending Authorization
Participants authorize spending for specific vibestreams:
function authorizeSpending (
uint256 vibeId ,
uint256 authorizedAmount
) external payable nonReentrant whenNotPaused
Requirements:
Must send tMETIS equal to authorizedAmount
Amount must not exceed MAX_ALLOWANCE (1000 tMETIS)
Vibestream must be registered and active
Process:
Validates payment amount
Creates or updates participant allowance
Refunds excess payment if any
Emits AllowanceAuthorized event
3. Joining Vibestreams
Participants join active vibestreams to begin payment processing:
function joinVibestream ( uint256 vibeId ) external nonReentrant
Requirements:
Must have sufficient allowance (≥ one minute of payments)
Cannot already be active in the vibestream
Vibestream must be registered
Process:
Sets participant as active
Records join timestamp
Adds to active participants list
Starts payment timer
4. Real-Time Payment Processing
Payments are processed automatically every 60 seconds:
function processPayments ( uint256 vibeId ) external
Payment Logic:
Calculate elapsed time since last deduction
Determine minutes elapsed (minimum 60 seconds)
Calculate amount owed: minutes × payPerMinute
Distribute payment: 80% creator, 20% treasury
Update participant’s spent amount and last deduction timestamp
5. Leaving Vibestreams
Participants can leave vibestreams to stop payments:
function leaveVibestream ( uint256 vibeId ) external nonReentrant
Process:
Processes final payment for elapsed time
Sets participant as inactive
Removes from active participants list
Emits ParticipantLeft event
Advanced Features
Allowance Management
Increasing Allowances
function increaseAllowance (
uint256 vibeId ,
uint256 additionalAmount
) external payable nonReentrant
Allows participants to add more funds to existing allowances without leaving the vibestream.
Emergency Stop
function emergencyStop (
uint256 vibeId ,
address participant ,
string calldata reason
) external
Immediately removes a participant from a vibestream. Can be called by:
Contract owner
Participant themselves
Vibestream creator
Payment Constants
Constant Value Description MIN_PAYMENT_INTERVAL60 seconds Minimum time between payments MAX_ALLOWANCE1000 tMETIS Maximum allowance per transaction treasuryFeePercent20% Treasury fee on all payments GAS_LIMIT50,000 Gas limit for external transfers
Security Features
Per-VibeID Isolation
Each allowance is tied to a specific vibestream, preventing cross-contamination:
mapping ( uint256 => mapping ( address => ParticipantAllowance)) public participantAllowances;
Reentrancy Protection
All payable functions use OpenZeppelin’s nonReentrant modifier:
function authorizeSpending ( uint256 vibeId , uint256 authorizedAmount )
external payable nonReentrant whenNotPaused
Emergency Controls
Pausable Operations
Contract can be paused to halt all operations:
function pause () external onlyOwner
function unpause () external onlyOwner
Emergency Withdrawal
Owner can withdraw stuck funds in emergencies:
function emergencyWithdraw () external onlyOwner
Gas Optimization
Limited External Calls
All external transfers use gas limits to prevent griefing:
( bool success, ) = payable (creator).call{
value : creatorAmount,
gas : GAS_LIMIT
}( "" );
Batch Processing
Multiple participants can be processed in a single transaction:
function processPayments ( uint256 vibeId ) external {
address [] memory participants = activeParticipants[vibeId];
for ( uint256 i = 0 ; i < participants.length; i ++ ) {
_processParticipantPayment (vibeId, participants[i]);
}
}
View Functions
function getParticipantAllowance ( uint256 vibeId , address participant )
external view returns ( ParticipantAllowance memory )
function getRemainingAllowance ( uint256 vibeId , address participant )
external view returns ( uint256 )
function getParticipantTime ( uint256 vibeId , address participant )
external view returns ( uint256 )
function getAmountOwed ( uint256 vibeId , address participant )
external view returns ( uint256 )
function getVibestreamConfig ( uint256 vibeId )
external view returns ( VibestreamConfig memory )
function getActiveParticipants ( uint256 vibeId )
external view returns ( address [] memory )
function getTotalRevenue ( uint256 vibeId )
external view returns ( uint256 )
Events
Core Events
event VibestreamRegistered (
uint256 indexed vibeId ,
address indexed creator ,
uint256 payPerMinute
);
event AllowanceAuthorized (
uint256 indexed vibeId ,
address indexed participant ,
uint256 authorizedAmount ,
uint256 payPerMinute
);
event ParticipantJoined (
uint256 indexed vibeId ,
address indexed participant ,
uint256 timestamp
);
event PaymentDeducted (
uint256 indexed vibeId ,
address indexed participant ,
address indexed creator ,
uint256 amount ,
uint256 timestamp
);
Usage Examples
Authorizing Spending
// Authorize 1 tMETIS for vibestream #123
ppmContract.authorizeSpending{value : 1 ether }( 123 , 1 ether );
Joining a Vibestream
// Join vibestream #123 (requires existing allowance)
ppmContract. joinVibestream ( 123 );
Processing Payments
// Process all pending payments for vibestream #123
ppmContract. processPayments ( 123 );
Emergency Exit
// Emergency stop for participant in vibestream #123
ppmContract. emergencyStop ( 123 , participantAddress, "User request" );
Integration with VibeFactory
The PPM contract integrates seamlessly with VibeFactory through automatic registration:
// In VibeFactory.createVibestream()
if (payPerStream && streamPrice > 0 && ppmContract != address ( 0 )) {
IPPM (ppmContract). registerVibestream (vibeId, msg.sender , streamPrice);
}
Next Steps
VibeKiosk Contract Learn about ticket sales
Contract Flows See interaction diagrams