Core Security Property
This is the foundational security property of the protocol. If the contract were compromised, paused, or abandoned, subscriber funds are unaffected - they are in the subscriber’s wallet, not in the contract.What If the Merchant Disappears?
The most common concern with subscription payments: what happens if the merchant goes offline, shuts down, or acts maliciously? Vowena provides four independent layers of protection, any one of which is sufficient to stop unauthorized charges.Layer 1: Direct on-chain cancellation
The subscriber can call
cancel(sub_id) directly on the smart contract from any Stellar-compatible interface - a wallet, a block explorer, or the CLI. No merchant cooperation needed.cancel() is a public contract function. It requires only the subscriber’s signature. It works even if the merchant’s website, API, and servers are completely offline.Layer 2: Universal Subscription Manager
The Vowena Dashboard is a universal subscription manager that works with any wallet. Connect your wallet, see every active subscription across all merchants, and cancel any of them with one click.
The dashboard reads directly from the blockchain. It does not depend on any merchant’s infrastructure. Even if Vowena’s own dashboard goes down, the contract functions remain accessible through any Soroban-compatible interface.
Layer 3: Auto-expiry via max_periods
If a plan has
max_periods set (e.g., 12 for an annual plan), the subscription automatically expires after that many billing periods. No action needed from anyone.Even if the subscriber loses access to their wallet or forgets about the subscription, billing stops automatically at the configured limit. For unlimited plans (
max_periods = 0), Layer 4 provides the backstop.Layer 4: Allowance expiration
The token allowance granted during
subscribe() has a ledger expiry - approximately 347 days at maximum. After this, the contract’s permission to pull funds expires automatically at the Soroban protocol level.This is the ultimate backstop. Even if the subscriber takes no action at all, the allowance expires and no further charges are possible. The subscriber would need to explicitly re-approve to continue.
Price Protection
Price ceiling
Every plan has an immutable
price_ceiling. The merchant can adjust amount within this range but never above it. Subscribers know the absolute worst-case charge per period at sign-up time.The ceiling is set at plan creation and can never be changed. No admin key, no governance vote, no emergency function can raise it.
Migration consent
To change pricing beyond the ceiling, the merchant must create a new plan and request migration. Each subscriber must explicitly accept the new terms by signing a new transaction.
Rejecting a migration keeps the subscriber on the old plan at the old price. The merchant cannot force the transition, cancel the old plan’s billing, or otherwise coerce acceptance.
Permissionless Charge Model
Why is charge() permissionless?
Why is charge() permissionless?
If
charge() required the merchant’s signature, the merchant becomes a single point of failure. If their key is lost, compromised, or their server goes down, billing stops. By removing the auth requirement, anyone can ensure billing continues on schedule.Can someone grief by calling charge() at the wrong time?
Can someone grief by calling charge() at the wrong time?
No. The contract enforces
next_billing_time - a charge call before the billing time simply returns false with no state change. You cannot charge early, charge twice, or charge a different amount.Can someone manipulate the charge amount?
Can someone manipulate the charge amount?
No. The amount is read from the plan’s on-chain data. The
charge() function takes only sub_id - there is no amount parameter. The contract determines the amount from the plan, and the subscriber approved the ceiling at subscription time.Can someone redirect funds?
Can someone redirect funds?
No. The
transfer_from call sends tokens directly to plan.merchant. The recipient is hardcoded in the plan struct, which can only be set at plan creation by the merchant themselves.Authorization Model
Vowena uses Soroban’s native authorization framework:| Action | Who Signs | What They Authorize |
|---|---|---|
create_plan | Merchant | Creating a plan under their address |
subscribe | Subscriber | The subscription AND the token allowance (single signature via auth tree) |
cancel | Subscriber | Cancelling their own subscription |
reactivate | Subscriber | Reactivating their paused subscription |
refund | Merchant | Transferring their own funds to the subscriber |
charge | Nobody | Permissionless - contract validates everything |
request_migration | Merchant | Flagging subscriptions for migration |
accept_migration | Subscriber | New subscription AND new token allowance |
reject_migration | Subscriber | Clearing the migration flag |
What the Contract Cannot Do
Understanding what the contract cannot do is as important as understanding what it can:Cannot hold funds
The contract has no balance. Tokens move directly from subscriber to merchant via
transfer_from. There is nothing to hack, drain, or freeze.Cannot charge above ceiling
The
amount is validated against price_ceiling on every update. The ceiling is immutable. The transfer amount is read from the plan, not passed as a parameter.Cannot charge early
Every
charge() call checks next_billing_time. Calls before the due time return false with no state change.Cannot prevent cancellation
cancel() checks only the subscriber’s auth and the subscription’s existence. No other condition can block it - not the merchant, not the admin, not the contract state.Comparison with Traditional Systems
| Risk | Credit Card | Vowena |
|---|---|---|
| Unauthorized charge amount | Possible (dispute after the fact) | Impossible (ceiling enforced by contract) |
| Charge after cancellation | Common complaint | Impossible (status check in charge()) |
| Merchant disappears, charges continue | Requires bank intervention | 4 independent self-service cancellation paths |
| Silent price increase | Email notice easily missed | Requires on-chain migration + explicit wallet signature |
| Funds at risk | Full credit line exposed | Only approved allowance, auto-expiring |
What’s Next
Billing
See the charge flow and understand the pre-check mechanism in detail.
Deployment
Deploy and verify the contract yourself.