Skip to main content

Core Security Property

The Vowena contract holds PERMISSION to pull funds, not the funds themselves. The contract never custodies, escrows, or temporarily holds any tokens. Subscriber funds remain in the subscriber’s wallet at all times. The contract only has a token allowance - a revocable permission - to transfer a specific amount to the merchant.
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.
1

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.
# Cancel from any terminal with Stellar CLI
stellar contract invoke \
  --id $CONTRACT_ID \
  --network mainnet \
  -- cancel \
  --subscriber $YOUR_ADDRESS \
  --sub_id 42
2

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.
3

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.
4

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

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.
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.
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.
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:
ActionWho SignsWhat They Authorize
create_planMerchantCreating a plan under their address
subscribeSubscriberThe subscription AND the token allowance (single signature via auth tree)
cancelSubscriberCancelling their own subscription
reactivateSubscriberReactivating their paused subscription
refundMerchantTransferring their own funds to the subscriber
chargeNobodyPermissionless - contract validates everything
request_migrationMerchantFlagging subscriptions for migration
accept_migrationSubscriberNew subscription AND new token allowance
reject_migrationSubscriberClearing the migration flag
There are no admin keys that can drain funds. The admin address (set during initialize) can only call extend_ttl to keep ledger entries alive. The admin cannot charge subscribers, cancel subscriptions, modify plans, or access any tokens. The admin role exists solely for TTL management.

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

RiskCredit CardVowena
Unauthorized charge amountPossible (dispute after the fact)Impossible (ceiling enforced by contract)
Charge after cancellationCommon complaintImpossible (status check in charge())
Merchant disappears, charges continueRequires bank intervention4 independent self-service cancellation paths
Silent price increaseEmail notice easily missedRequires on-chain migration + explicit wallet signature
Funds at riskFull credit line exposedOnly 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.