Architecture & Docs

A comprehensive guide to how Vypr Pad is designed and functions

Overview

Vypr Pad is a headless token launchpad built on Base chain using Vyper smart contracts. The system enables connectionless, approval-free token creation and trading through bonding curve economics. Unlike traditional DEXs that require wallet connections, function calls, and token approvals, Vypr Pad allows users to interact with tokens using simple ETH transfers and ERC20 transfers.

Sequence diagram showing token creation, buying, and selling flows

Sequence diagram showing the three main user interactions: token creation, buying tokens, and selling tokens

The platform is designed with AI agents, scripts, and autonomous systems in mind—any system that can send ETH or transfer tokens can interact with Vypr Pad without complex integration requirements.

Deployment Information

Vypr Pad contracts are deployed on Base Mainnet and Base Sepolia. The factory contracts are accessible via ENS names for easy interaction.

Base Mainnet

ENS Name: vypr.eth
Chain ID: 8453
Contract Address
Factory 0x458366909fE9CfCB6baEC17F6adA9FFb6aA07bC5
Token Blueprint 0xF431C8C16a25AECf1aa7B2cF409659e429b0ac56
Pool Blueprint 0x5C64257aFf80B690341D1905Ea1FEcB17a151882

Base Sepolia

ENS Name: sepolia.vypr.eth
Chain ID: 84532
Contract Address
Factory 0x1278962a31fd330fA7eCF99756a502088C44353D
Token Blueprint 0x21Ca1900466969aC909612560d9e460230f2b0Bd
Pool Blueprint 0x458366909fE9CfCB6baEC17F6adA9FFb6aA07bC5

Note: Individual token and pool contracts are deployed dynamically when tokens are created. Use the factory address (or ENS name) to create new tokens, or query the factory to discover existing tokens.

Two-Contract Architecture

Why Two Contracts?

The system uses a two-contract architecture to solve a critical UX problem with wallet software. Initially, a single contract was designed to handle both token and pool functionality. However, MetaMask and other wallet software block sending ETH directly to token contracts as a safety measure.

Solution: Split the system into two separate contracts:
  • BondingCurveToken.vy - Pure ERC20 token (no ETH handling)
  • BondingCurvePool.vy - Handles ETH reserves and bonding curve logic

This separation allows users to send ETH to the pool contract (which MetaMask doesn't block) while maintaining full headless functionality. From the user's perspective, they interact with one canonical address (the pool), but the architecture works seamlessly with wallet UX constraints.

Contract Relationships

Factory
Pool
Token

The BondingCurveFactory deploys pairs of BondingCurvePool and BondingCurveToken contracts. Each pool and token are tightly coupled:

  • The pool holds the token address and can mint/burn tokens
  • The token holds the pool address and triggers redemption when transferred to the pool
  • Both contracts use reentrancy guards to prevent attacks

Smart Contract Components

BondingCurveFactory

The factory contract is responsible for deploying new token/pool pairs. It uses blueprint contracts for gas-efficient deployments via create_from_blueprint.

Key Functions:

  • create_curve() - Deploy a new token/pool pair with custom parameters
  • __default__() - Headless token creation: send ETH to factory to auto-create a token
  • get_curve() - Retrieve token and pool addresses by index

The factory maintains mappings to track all created curves: pool_to_token, token_to_pool, and creator_of for indexing and discovery.

BondingCurvePool

The pool contract is the core of the bonding curve system. It holds the ETH reserve, calculates prices, and handles all buy/sell operations.

State Variables:

  • token - Address of the associated token contract
  • reserve - Current ETH reserve (18 decimals)
  • base_price - Starting price in 1e18 fixed point
  • slope - Price increase per token in 1e18 fixed point
  • fee_buy_bps / fee_sell_bps - Trading fees in basis points
  • fee_recipient - Creator address (receives 80% of fees)
  • protocol_recipient - Factory owner (receives 20% of fees)

Key Functions:

  • buy() - Explicit function to buy tokens with ETH
  • __default__() - Headless minting: send ETH directly to pool address
  • sell() - Explicit function to sell tokens for ETH
  • on_redeem() - Callback from token contract for headless redemption
  • get_price() - Calculate price at a given supply level
  • get_buy_amount_out() - Calculate tokens received for ETH input
  • get_sell_amount_out() - Calculate ETH received for token input

BondingCurveToken

A standard ERC20 token with restricted mint/burn permissions. Only the associated pool can mint or burn tokens. The token implements headless redemption by detecting transfers to the pool address.

Key Functions:

  • transfer() - Standard ERC20 transfer, with special handling for pool address
  • transferFrom() - Standard ERC20 transferFrom, with special handling for pool address
  • mint() - Only callable by pool contract
  • burn() - Only callable by pool contract

When tokens are transferred to the pool address, the token contract automatically:

  1. Burns the tokens (reduces total supply)
  2. Calls pool.on_redeem() with the sender's address
  3. The pool calculates ETH refund and sends it to the token owner

Bonding Curve Mathematics

Vypr Pad uses a linear bonding curve model where price increases linearly with supply. This creates predictable price discovery without requiring order books or liquidity pools.

Price Function

The price at any supply level is calculated as:

P(s) = base_price + slope * s

Where:

  • P(s) = Price at supply level s (in ETH per token, 18 decimals)
  • base_price = Starting price (1e18 fixed point)
  • slope = Price increase per token (1e18 fixed point)
  • s = Current token supply (18 decimals)

Buy Calculation (ETH → Tokens)

When buying tokens, the cost is calculated by integrating the price function over the supply range:

cost = base_price * Δs + slope * ((s + Δs)² - s²) / 2

This is solved using the quadratic formula to determine how many tokens can be bought with a given amount of ETH. The pool contract implements this in _calculate_tokens_for_eth().

Sell Calculation (Tokens → ETH)

When selling tokens, the refund is calculated using the average price over the tokens being sold:

refund = Δs * (base_price + slope * (2s - Δs) / 2)

This ensures sellers receive a fair price based on the bonding curve. The pool contract implements this in _calculate_eth_for_tokens().

Example

With base_price = 0.01 ETH and slope = 0.000001 ETH:

  • At supply 0: Price = 0.01 ETH
  • At supply 1,000: Price = 0.01 + (0.000001 × 1,000) = 0.011 ETH
  • At supply 10,000: Price = 0.01 + (0.000001 × 10,000) = 0.02 ETH

Headless Interaction Patterns

"Headless" refers to operations that don't require explicit function calls. Users can interact with tokens using simple transfers, making the system compatible with any wallet or script that can send ETH or transfer ERC20 tokens.

Headless Minting (ETH → Tokens)

Users can buy tokens by simply sending ETH directly to the pool contract address. The pool's __default__() fallback function automatically:

  1. Calculates tokens to mint based on ETH received
  2. Deducts trading fees (if any)
  3. Updates the ETH reserve
  4. Mints tokens to the sender
User Experience: No wallet connection needed, no function calls, no approvals. Just send ETH to the pool address like sending to any other wallet.

Headless Redemption (Tokens → ETH)

Users can sell tokens by transferring them to the pool contract address. The token contract's transfer() function detects when the recipient is the pool and:

  1. Burns the tokens (reduces total supply)
  2. Calls pool.on_redeem() with the sender's address
  3. The pool calculates ETH refund based on bonding curve
  4. Deducts trading fees (if any)
  5. Sends ETH back to the token owner
User Experience: Standard ERC20 transfer operation. Works with any wallet that supports token transfers. No special function calls required.

Headless Token Creation

Users can create new tokens by sending ETH directly to the factory contract. The factory's __default__() function:

  1. Requires minimum 0.001 ETH (creation fee)
  2. Deducts 0.001 ETH as fee to factory owner
  3. Auto-generates token name and symbol
  4. Deploys new token/pool pair with default parameters
  5. If extra ETH sent, uses it to seed initial liquidity
  6. Mints initial tokens to creator

Factory Pattern

The factory contract uses a blueprint pattern for gas-efficient deployments. Blueprint contracts are pre-deployed contracts whose bytecode is reused when creating new instances.

Deployment Flow

  1. Factory deploys pool blueprint (if not already deployed)
  2. Factory deploys token blueprint (if not already deployed)
  3. When creating a curve:
    1. Deploy pool instance from blueprint
    2. Deploy token instance from blueprint (pointing to pool)
    3. Initialize pool with token address
    4. Record mappings in factory

Curve Tracking

The factory maintains several mappings for indexing and discovery:

  • curves[index] - Array-like mapping of pool addresses
  • pool_to_token[pool] - Get token address from pool
  • token_to_pool[token] - Get pool address from token
  • creator_of[pool] - Get creator address from pool

These mappings enable the front-end to discover all tokens, link tokens to pools, and display creator information.

Fee Structure

Trading fees are configurable per curve (up to 10% maximum) and are collected in ETH on both buy and sell operations. Fees are split between the token creator and the protocol.

Fee Distribution

  • 80% to fee_recipient (token creator)
  • 20% to protocol_recipient (factory owner)

This split is hardcoded at PROTOCOL_FEE_SHARE_BPS = 2000 (20% of total fees).

Buy Fee Flow

  1. User sends ETH to pool
  2. Fee calculated: fee = eth_in × fee_buy_bps ÷ 10000
  3. Fee split: 80% to creator, 20% to protocol
  4. Net ETH (after fee) goes into reserve
  5. Tokens calculated based on net ETH

Sell Fee Flow

  1. User transfers tokens to pool
  2. Gross ETH calculated from bonding curve
  3. Gross ETH deducted from reserve
  4. Fee calculated: fee = eth_out_gross × fee_sell_bps ÷ 10000
  5. Fee split: 80% to creator, 20% to protocol
  6. Net ETH (after fee) sent to user
Important: Fee recipients must be Externally Owned Accounts (EOAs), not smart contracts. Fee transfers use send() which will revert if the recipient is a contract without a payable fallback function.

Front-End Architecture

The front-end is a static web application built with Vue.js that provides real-time visibility into bonding curve activity. It connects to The Graph subgraph for efficient blockchain data querying.

Technology Stack

  • Vue.js 3 - Reactive front-end framework
  • Ethers.js 5.7 - Ethereum interaction library
  • The Graph - Decentralized indexing protocol for blockchain data
  • Chart.js - Data visualization for trading activity

Data Flow

  1. Subgraph Indexing: The Graph subgraph indexes blockchain events (CurveCreated, Bought, Sold) and stores token/pool data
  2. GraphQL Queries: Front-end queries The Graph API using GraphQL to fetch:
    • All created tokens with metadata
    • Token holder information
    • Trading activity (mints and redemptions)
    • Real-time price and supply data
  3. Direct RPC Calls: For real-time data not yet indexed, the front-end makes direct RPC calls to:
    • Get current token supply
    • Get current ETH reserve
    • Get current price
    • Get token holder balances
  4. Display: Data is formatted and displayed in Vue components with real-time updates

Key Components

  • index.html - Main discovery page showing all tokens
  • token-screen.html - Individual token detail page with charts and holder information
  • creators.html - Page showing all tokens created by a specific wallet
  • graph.js - GraphQL query utilities and API endpoint resolution
  • common.js - Shared utilities (formatting, address handling)
  • networks.js - Network configuration (Base Sepolia, Base Mainnet)

Network Configuration

The front-end supports multiple networks through the networks.js configuration file. Each network specifies:

  • RPC endpoint
  • Chain ID
  • Factory contract address
  • The Graph subgraph endpoint

Users can switch networks via a dropdown, and the preference is saved in localStorage.

API Key Security with Netlify Edge Functions

The Graph Studio API requires an API key for authentication, but API keys must never be exposed in client-side code. To solve this, Vypr Pad uses Netlify Edge Functions as a secure proxy.

How It Works

  1. Edge Function: A Netlify Edge Function at /api/subgraph acts as a proxy
  2. Environment Variables: The API key and Graph Studio URL are stored as Netlify environment variables:
    • GRAPH_API_KEY - The Graph Studio API key
    • GRAPH_STUDIO_URL - The Graph Studio query endpoint
  3. Request Flow:
    1. Front-end sends GraphQL query to /api/subgraph
    2. Edge function receives the query
    3. Edge function adds the API key to the Authorization header
    4. Edge function forwards the query to The Graph Studio API
    5. Response is returned to the front-end
Security Benefits: The API key never leaves Netlify's server environment. It's never exposed in browser JavaScript, network requests, or client-side code. The edge function also includes basic security measures like query size limits and introspection blocking.

Localhost Development Fallback

For local development, the front-end automatically detects when running on localhost and uses a public Graph Studio testing URL instead of the Netlify edge function. This allows developers to work locally without needing Netlify's environment variables.

The URL resolution logic in graph.js:

function resolveGraphApiUrl() {
    // Check for localStorage override (for testing)
    const override = window.localStorage?.getItem('vypr-pad-graph-endpoint');
    if (override) {
        return override;
    }

    // Detect localhost
    const host = window.location?.hostname || '';
    const isLocalhost = host === 'localhost' || host === '127.0.0.1' || host === '[::1]';
    
    // Use testing URL for localhost, production edge function otherwise
    return isLocalhost ? DEV_GRAPH_API_URL : PROD_GRAPH_API_URL;
}

This means:

  • Production (Netlify): Uses /api/subgraph edge function with secure API key
  • Localhost: Uses public Graph Studio testing URL (no API key needed)
  • Override: Developers can set a custom endpoint in localStorage for testing

Security Considerations

Reentrancy Protection

Both pool and token contracts use boolean reentrancy guards (locked flag) to prevent reentrancy attacks. All external calls are protected:

  • Pool: buy(), sell(), __default__(), on_redeem()
  • Token: transfer(), transferFrom()

Access Control

  • Only pool can mint/burn tokens
  • Only token contract can call pool.on_redeem()
  • Only factory can initialize pool token address

Integer Safety

Vyper's built-in safe math prevents integer overflow/underflow. All calculations use fixed-point arithmetic with 18 decimals for precision.

Reserve Validation

Sell operations verify that the calculated ETH output doesn't exceed the available reserve, preventing reserve depletion attacks.

Data Availability

The front-end uses The Graph subgraph for efficient data querying. The subgraph indexes:

  • CurveCreated events - New token deployments
  • Bought events - Token purchases
  • Sold events - Token redemptions
  • Transfer events - Token transfers (for holder tracking)

This allows the front-end to display comprehensive token information, trading history, and holder data without making expensive direct RPC calls for every piece of data.