Subscriptions.sol
Overview
The Subscriptions.sol contract provides two payment models for continuous AI agent services on Nexis: epoch-based subscriptions (periodic fixed payments) and rate-based streams (continuous per-second payments). This dual-model approach supports both traditional subscription patterns and novel streaming payment use cases. Contract Location:/nexis-appchain/packages/contracts-bedrock/contracts/Subscriptions.sol
Key Features
- Epoch Subscriptions: Fixed amount payments at regular intervals (daily, weekly, monthly)
- Payment Streams: Continuous per-second payment flows with on-demand withdrawals
- Multi-Asset Support: ETH and ERC20 token payments
- Prefunding: Optional upfront funding for multiple periods
- Flexible Cancellation: Cancel anytime with automatic refunds
- Agent Integration: Direct payments to agent owners via Agents.sol
Architecture
Payment Models Comparison
| Feature | Epoch Subscriptions | Rate-Based Streams | 
|---|---|---|
| Payment Frequency | Fixed intervals (1 day, 1 week, 1 month) | Continuous (per second) | 
| Processing | Manual processSubscription()call | Automatic accrual, manual withdrawal | 
| Typical Use Case | Monthly API access, tier-based services | Pay-per-use, metered billing, real-time services | 
| Prefunding | Multiple epochs upfront | Full duration upfront | 
| Withdrawal | Automatic on processing | Agent withdraws accrued amount anytime | 
| Cancellation | Refund unused balance | Refund unstreamed portion | 
| Gas Efficiency | Lower (batch processing) | Higher (continuous calculation) | 
Core Data Structures
Subscription
Stream
Contract Roles
| Role | Bytes32 Identifier | Description | 
|---|---|---|
| DEFAULT_ADMIN_ROLE | 0x00 | Administrative control, can cancel subscriptions/streams | 
| PAUSER_ROLE | keccak256("PAUSER_ROLE") | Emergency pause capability | 
Epoch-Based Subscriptions
createSubscription
Create a new epoch-based subscription to an agent.| Parameter | Type | Description | 
|---|---|---|
| agentId | uint256 | Agent to subscribe to | 
| asset | address | Payment asset ( address(0)for ETH) | 
| amountPerEpoch | uint256 | Payment amount per epoch | 
| epochDuration | uint64 | Epoch duration in seconds (e.g., 86400 = 1 day) | 
| prefundEpochs | uint8 | Number of epochs to prepay (0-255) | 
| metadataURI | string | Subscription details (service tier, features, etc.) | 
subscriptionId - Unique subscription identifier
Payment:
- For ETH: msg.valuemust equalamountPerEpoch × prefundEpochs
- For ERC20: Caller must approve contract to spend amountPerEpoch × prefundEpochs
- SubscriptionCreated(...)
- SubscriptionFunded(...)(if prefunded)
fundSubscription
Add funds to an existing subscription.- subscriptionId: Subscription ID
- epochs: Number of epochs to fund
- Subscription must be active
SubscriptionFunded(uint256 indexed subscriptionId, uint256 amount, address indexed funder)
Example:
processSubscription
Process a subscription payment (can be called by anyone).- Subscription is active
- Current time >= nextCharge
- Balance >= amountPerEpoch
- Deducts amountPerEpochfrom balance
- Increments nextChargebyepochDuration
- Transfers payment to agent owner
- Emits SubscriptionProcessed
SubscriptionProcessed(uint256 indexed subscriptionId, address indexed recipient, uint256 amount, uint64 nextCharge)
Example (Manual Processing):
cancelSubscription
Cancel a subscription and refund remaining balance.DEFAULT_ADMIN_ROLE
Behavior:
- Sets subscription to inactive
- Refunds remaining balance to payer
SubscriptionCancelled(uint256 indexed subscriptionId, address indexed payer, uint256 refundedAmount)
Example:
getSubscription
Query subscription details.Rate-Based Payment Streams
createStream
Create a continuous payment stream to an agent.| Parameter | Type | Description | 
|---|---|---|
| agentId | uint256 | Agent receiving stream | 
| asset | address | Payment asset | 
| totalAmount | uint256 | Total stream amount | 
| start | uint64 | Stream start timestamp | 
| end | uint64 | Stream end timestamp | 
| integrationURI | string | Integration details, API keys, etc. | 
- totalAmount % (end - start) == 0(evenly divisible rate)
- end > start
- Full totalAmountmust be provided upfront
StreamCreated(...)
Example (7-Day Stream):
withdrawFromStream
Withdraw accrued stream payments (agent owner only).- Calculates withdrawable amount based on elapsed time
- Transfers to agent owner
- Updates withdrawnamount
StreamWithdrawn(uint256 indexed streamId, address indexed recipient, uint256 amount)
Example:
cancelStream
Cancel a stream and refund unstreamed portion.DEFAULT_ADMIN_ROLE
Behavior:
- Calculates and transfers any withdrawable amount to agent owner
- Calculates unstreamed amount
- Refunds unstreamed amount to payer
- Sets stream inactive
- StreamWithdrawn(...)(if withdrawable > 0)
- StreamCancelled(uint256 indexed streamId, address indexed payer, uint256 refundedAmount)
getStream
Query stream details.Events Reference
Subscription Events
Stream Events
Use Cases & Examples
Use Case 1: SaaS API Subscription
Use Case 2: Pay-Per-Inference (Streaming)
Use Case 3: Tiered Subscription with Auto-Renewal
Use Case 4: Escrow with Time-Release
Admin Functions
pause / unpause
Emergency pause contract operations.setAgents
Update Agents.sol contract reference.Integration Patterns
Subscription Dashboard
Stream Dashboard
Security Considerations
Reentrancy Protection
All state-changing functions with transfers usenonReentrant modifier.
Rate Calculation
- Stream rates must divide evenly (totalAmount % duration == 0)
- Prevents rounding errors and dust amounts
Authorization
- Only agent owners can withdraw from streams
- Only payers (or admin) can cancel subscriptions/streams
Time Manipulation
- Uses block.timestampfor time calculations
- Miners can manipulate up to ~15 seconds
- Not critical for hourly/daily payments
Gas Optimization
- Subscription Processing: Use bots to batch-process multiple subscriptions
- Stream Withdrawals: Agents should withdraw periodically (e.g., weekly) rather than frequently
- Prefunding: Pay for multiple epochs upfront to reduce transaction costs
Related Contracts
- Agents.sol - Validates agent existence and retrieves owner addresses
- Tasks.sol - Alternative one-time payment model
- Treasury.sol - Could integrate for protocol fees on subscriptions
ABI & Deployment
ABI Location:/nexis-appchain/packages/contracts-bedrock/artifacts/contracts/Subscriptions.sol/Subscriptions.json
Network Addresses:
| Network | Contract Address | Explorer | 
|---|---|---|
| Nexis Mainnet | 0x... | View Contract | 
| Nexis Testnet | 0x... | View Contract | 
Support & Resources
- GitHub: nexis-network/nexis-appchain
- Discord: Nexis Community
- Documentation: nex-t1.ai