Deployment Guide

Comprehensive deployment scripts and guides for deploying the LSSVM protocol to Base Mainnet, Base Sepolia testnet, or local development environments.

Quick Start

Local Development

cd packages/lssvm-contracts
anvil  # In one terminal
./deploy-local.sh  # In another terminal

Base Sepolia Testnet

cd packages/lssvm-contracts
./deploy-base-testnet.sh
./deploy-test-nfts.sh  # Optional: Deploy test NFTs

Base Mainnet

cd packages/lssvm-contracts
./deploy-base.sh
⚠️ Always test deployments on testnet before deploying to mainnet

Deployment Documentation

Base Mainnet Deployment

Base Mainnet Deployment Summary

Deployment Date: $(date) Deployer: 0x6dA173B1d50F7Bc5c686f8880C20378965408344 Chain: Base Mainnet (8453) Status: ✅ Successfully Deployed

Deployed Contracts

Core Contracts

  • RoyaltyEngine: 0x8a492D8d41bE9886E4f7ee7572cEE4eE9DA364E1
  • LSSVMPairERC721ETH: 0x577C0A55a7C8189F31C22F39e41FA2A8DcB40bad
  • LSSVMPairERC721ERC20: 0x12AA8645252D5FEceCf467724CdDD83093069E9f
  • LSSVMPairERC1155ETH: 0xF130207fbE0913b5470732D25699E41F5Ea4da7f
  • LSSVMPairERC1155ERC20: 0x68f397655a5a1478e24Bdb52D0Df33e50AB6Ce28
  • LSSVMPairFactory: 0xF6B4bDF778db19DD5928248DE4C18Ce22E8a5f5e

Router

  • VeryFastRouter: 0x4352c72114C4b9c4e1F8C96347F2165EECaDeb5C

Configuration

Bonding Curves (Base Mainnet)

All bonding curves are whitelisted:

  • LinearCurve: 0xe41352CB8D9af18231E05520751840559C2a548A
  • ExponentialCurve: 0x9506C0E5CEe9AD1dEe65B3539268D61CCB25aFB6
  • XykCurve: 0xd0A2f4ae5E816ec09374c67F6532063B60dE037B
  • GDACurve: 0x4f1627be4C72aEB9565D4c751550C4D262a96B51

Router Status

  • Router: 0x4352c72114C4b9c4e1F8C96347F2165EECaDeb5C ✅ Whitelisted

Factory Configuration

  • Owner: 0x6dA173B1d50F7Bc5c686f8880C20378965408344
  • Protocol Fee Recipient: Set in deployment
  • Protocol Fee Multiplier: 1% (0.01e18)

Deployment Transaction

Total Gas Used: 28,812,538 gas Total Cost: ~0.0000085 ETH Block: 38239761

Next Steps

1. Update Miniapp Configuration

Add to apps/miniapp/.env.local:

# Base Mainnet (chainId: 8453)
NEXT_PUBLIC_FACTORY_ADDRESS_8453=0xF6B4bDF778db19DD5928248DE4C18Ce22E8a5f5e
NEXT_PUBLIC_ROUTER_ADDRESS_8453=0x4352c72114C4b9c4e1F8C96347F2165EECaDeb5C

2. Verify Contracts (Optional)

Contract verification failed due to API key rate limiting. You can verify manually later:

  1. Go to https://basescan.org/
  2. Search for each contract address
  3. Click "Contract" tab → "Verify and Publish"
  4. Use the verification parameters from the deployment

3. Test Deployment

Test the deployed contracts:

  • Create a test pool
  • Verify pool appears in browse page
  • Test buying/selling NFTs

Links

  • Factory on BaseScan: https://basescan.org/address/0xF6B4bDF778db19DD5928248DE4C18Ce22E8a5f5e
  • Router on BaseScan: https://basescan.org/address/0x4352c72114C4b9c4e1F8C96347F2165EECaDeb5C
  • RoyaltyEngine on BaseScan: https://basescan.org/address/0x8a492D8d41bE9886E4f7ee7572cEE4eE9DA364E1

Notes

  • All contracts are deployed and functional
  • Bonding curves are deployed on Base Mainnet (separate from Ethereum Mainnet deployments)
  • Factory is fully configured and ready to use
  • Contract verification can be completed later (not critical for functionality)

Factory Configuration Status

All bonding curves are correctly whitelisted on Base Mainnet.

The factory has been configured with the correct Base Mainnet bonding curve addresses:

  • Base Mainnet addresses are whitelisted ✅
  • Ethereum Mainnet addresses have been removed ✅

Verification:

  • Base LinearCurve (0xe41352CB8D9af18231E05520751840559C2a548A): ✅ Whitelisted
  • Base ExponentialCurve (0x9506C0E5CEe9AD1dEe65B3539268D61CCB25aFB6): ✅ Whitelisted
  • Base XykCurve (0xd0A2f4ae5E816ec09374c67F6532063B60dE037B): ✅ Whitelisted
  • Base GDACurve (0x4f1627be4C72aEB9565D4c751550C4D262a96B51): ✅ Whitelisted
Base Testnet Deployment

Base Sepolia Testnet Deployment Summary

Deployment Date: December 2024 Deployer: 0x6dA173B1d50F7Bc5c686f8880C20378965408344 Chain: Base Sepolia Testnet (84532) Status: ✅ Successfully Deployed

Deployed Contracts

Bonding Curves

  • LinearCurve: 0x3F1E31d662eD24b6B69d73B07C98076d3814F8C0
  • ExponentialCurve: 0x4637d06530d5D375B1D5dE1117C98b0c6EA7eDd1
  • XykCurve: 0xC4DfB54Ca18c9e5EC2a23e8DE09588982A6b2242
  • GDACurve: 0x60bAB2734eb85F07Ca93E3B7Fb1015fcc5e9CbA7

Core Contracts

  • RoyaltyEngine: 0xc51303BfE0a4d268137a0910073f907dCB8Bc51f
  • LSSVMPairERC721ETH: 0x723124567064B038e6fA2C247E8815B06443C43a
  • LSSVMPairERC721ERC20: 0x3CEE515879FFe4620a1F8aC9bf09B97e858815Ef
  • LSSVMPairERC1155ETH: 0x065Ab76c7e9Edcfb3bF25B9076235e7A5ffA76f4
  • LSSVMPairERC1155ERC20: 0x1Cb0c1F72Ba7547fC99c4b5333d8aBA1eD6b31A9
  • LSSVMPairFactory: 0x372990Fd91CF61967325dD5270f50c4192bfb892

Router

  • VeryFastRouter: 0x6C9e6BAc4255901EaD3447C07917967E9dBc32d3

Configuration

Bonding Curves Status

All bonding curves are whitelisted:

  • LinearCurve: 0x3F1E31d662eD24b6B69d73B07C98076d3814F8C0
  • ExponentialCurve: 0x4637d06530d5D375B1D5dE1117C98b0c6EA7eDd1
  • XykCurve: 0xC4DfB54Ca18c9e5EC2a23e8DE09588982A6b2242
  • GDACurve: 0x60bAB2734eb85F07Ca93E3B7Fb1015fcc5e9CbA7

Router Status

  • Router: 0x6C9e6BAc4255901EaD3447C07917967E9dBc32d3 ✅ (Whitelisted)

Factory Owner

  • Owner: 0x6dA173B1d50F7Bc5c686f8880C20378965408344 ✅ (Matches Deployer)

Protocol Fees

  • Recipient: Configured via environment variable ✅
  • Multiplier: Configured via environment variable ✅

Deployment Details

Gas Usage

  • Total Gas Used: 31,155,320 gas
  • Total Cost: ~0.000031 ETH (testnet)
  • Average Gas Price: 0.001000062 gwei

Transaction Hashes

All transactions were successfully broadcast to Base Sepolia testnet. Key transactions:

  • Factory deployment: 0xc2cfa6bb8b9d0d4cfdefcb1a9294141f0c33f32a3fb0616c07e0513e38cffab3
  • Router deployment: 0x801a68bb07db736193f4bfa57c4875a8ce79c756b96628405a62baa1a60c3717
  • Bonding curve whitelisting: Multiple transactions (see full deployment logs)

Verification Status

  • BaseScan Sepolia Verification: ❌ Failed due to "Too many invalid api key attempts, please try again later"
    • Note: Contracts are deployed and functional. Verification can be performed manually later.

BaseScan Links

  • Factory on BaseScan Sepolia: https://sepolia.basescan.org/address/0x372990Fd91CF61967325dD5270f50c4192bfb892
  • Router on BaseScan Sepolia: https://sepolia.basescan.org/address/0x6C9e6BAc4255901EaD3447C07917967E9dBc32d3
  • RoyaltyEngine on BaseScan Sepolia: https://sepolia.basescan.org/address/0xc51303BfE0a4d268137a0910073f907dCB8Bc51f

Notes

  • All contracts are deployed and functional on Base Sepolia testnet
  • Bonding curves were deployed fresh (not reused from mainnet)
  • Factory is fully configured and ready to use
  • Contract verification can be completed later (not critical for functionality)
  • This is a testnet deployment - use testnet ETH only

Test NFT Contracts

Test NFT contracts have been deployed for testing pools:

For detailed information on using these test NFTs, see TEST_NFTS.md.

Next Steps

  1. Update Miniapp Configuration: Edit apps/miniapp/.env.local with the following:

    NEXT_PUBLIC_FACTORY_ADDRESS_84532=0x372990Fd91CF61967325dD5270f50c4192bfb892
    NEXT_PUBLIC_ROUTER_ADDRESS_84532=0x6C9e6BAc4255901EaD3447C07917967E9dBc32d3
    

    Restart your Next.js dev server after updating for changes to take effect.

  2. Test the Deployment:

    • Create a test pool using the deployed factory and test NFTs
    • Use TestNFT721 for ERC721/ETH pools
    • Use TestNFT1155 for ERC1155/ETH pools
    • Verify the pool appears in the miniapp
    • Test buying and selling NFTs on testnet
  3. Manual Contract Verification (Optional): If desired, manually verify the deployed contracts on BaseScan Sepolia.

  4. Get Testnet ETH: If you need more testnet ETH for testing:

    • Coinbase Base Sepolia Faucet: https://www.coinbase.com/faucets/base-ethereum-goerli-faucet
    • Base Bridge: https://bridge.base.org/deposit
Deploy to Base

Base Mainnet Deployment Guide

This guide walks you through deploying your own factory and router contracts to Base Mainnet, reusing sudoswap's stateless bonding curves.

Prerequisites

  1. Foundry installed: forge --version should work
  2. Base Mainnet RPC: Get an RPC endpoint (Alchemy, Infura, or public)
  3. Deployment account: Account with sufficient ETH for gas fees
  4. Environment variables: Set up in .env.local (see below)

Step 1: Set Up Environment Variables

Create packages/lssvm-contracts/.env.local with the following:

# Network Configuration
RPC_URL=https://mainnet.base.org
# Or use your own RPC endpoint:
# RPC_URL=https://base-mainnet.g.alchemy.com/v2/YOUR_API_KEY

# Deployment Account
PRIVATE_KEY=your_private_key_here

# Contract Verification (optional but recommended)
ETHERSCAN_API_KEY=your_base_scan_api_key_here

# Contract Configuration
# Manifold Royalty Registry for Base Mainnet
# For Base and most EVM chains, use the universal address:
ROYALTY_REGISTRY=0xad2184fb5dbcfc05d8f056542fb25b04fa32a95d

# Address that will receive protocol trading fees
PROTOCOL_FEE_RECIPIENT=0xYourFeeRecipientAddress

# Protocol fee multiplier (in base 1e18)
# Example: 0.01e18 = 1%, 0.05e18 = 5%
# Maximum: 0.1e18 (10%)
PROTOCOL_FEE_MULTIPLIER=10000000000000000

# Address that will own the factory contract
# This address can whitelist bonding curves, routers, and update fees
FACTORY_OWNER=0xYourFactoryOwnerAddress

Important: Replace all placeholder addresses with your actual addresses.

Step 2: Deploy Contracts

Run the deployment script:

cd packages/lssvm-contracts

# Load environment variables
source .env.local

# Deploy all contracts
forge script script/DeployForBase.s.sol:DeployForBase \
  --rpc-url $RPC_URL \
  --broadcast \
  --verify \
  --sender $(cast wallet address $PRIVATE_KEY) \
  -vvvv

The script will:

  1. Deploy RoyaltyEngine
  2. Deploy all 4 pair templates (ERC721ETH, ERC721ERC20, ERC1155ETH, ERC1155ERC20)
  3. Deploy LSSVMPairFactory
  4. Deploy VeryFastRouter
  5. Automatically whitelist sudoswap's bonding curves (if deployer is factory owner)
  6. Automatically whitelist the router (if deployer is factory owner)

Step 3: Verify Deployment

After deployment, the script will print a summary with all contract addresses. Save these addresses!

Verify the factory was deployed correctly:

# Replace FACTORY_ADDRESS with the actual address from deployment
FACTORY_ADDRESS=0x...

cast call $FACTORY_ADDRESS "owner()" --rpc-url $RPC_URL
cast call $FACTORY_ADDRESS "protocolFeeRecipient()" --rpc-url $RPC_URL

Verify bonding curves are whitelisted:

# Sudoswap bonding curve addresses (Base Mainnet)
LINEAR_CURVE=0xe41352CB8D9af18231E05520751840559C2a548A
EXPONENTIAL_CURVE=0x9506C0E5CEe9AD1dEe65B3539268D61CCB25aFB6
XYK_CURVE=0xd0A2f4ae5E816ec09374c67F6532063B60dE037B
GDA_CURVE=0x4f1627be4C72aEB9565D4c751550C4D262a96B51

cast call $FACTORY_ADDRESS "bondingCurveAllowed(address)" $LINEAR_CURVE --rpc-url $RPC_URL
cast call $FACTORY_ADDRESS "bondingCurveAllowed(address)" $EXPONENTIAL_CURVE --rpc-url $RPC_URL
cast call $FACTORY_ADDRESS "bondingCurveAllowed(address)" $XYK_CURVE --rpc-url $RPC_URL
cast call $FACTORY_ADDRESS "bondingCurveAllowed(address)" $GDA_CURVE --rpc-url $RPC_URL

Verify router is whitelisted:

# Replace ROUTER_ADDRESS with the actual address from deployment
ROUTER_ADDRESS=0x...

cast call $FACTORY_ADDRESS "routerStatus(address)" $ROUTER_ADDRESS --rpc-url $RPC_URL

Step 4: Manual Configuration (If Needed)

If the deployer is not the factory owner, you'll need to manually whitelist the bonding curves and router:

# Set your addresses
FACTORY_ADDRESS=0x...
ROUTER_ADDRESS=0x...
PRIVATE_KEY=your_private_key

# Whitelist bonding curves (Base Mainnet addresses)
cast send $FACTORY_ADDRESS \
  "setBondingCurveAllowed(address,bool)" \
  0xe41352CB8D9af18231E05520751840559C2a548A true \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL

cast send $FACTORY_ADDRESS \
  "setBondingCurveAllowed(address,bool)" \
  0x9506C0E5CEe9AD1dEe65B3539268D61CCB25aFB6 true \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL

cast send $FACTORY_ADDRESS \
  "setBondingCurveAllowed(address,bool)" \
  0xd0A2f4ae5E816ec09374c67F6532063B60dE037B true \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL

cast send $FACTORY_ADDRESS \
  "setBondingCurveAllowed(address,bool)" \
  0x4f1627be4C72aEB9565D4c751550C4D262a96B51 true \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL

# Whitelist router
cast send $FACTORY_ADDRESS \
  "setRouterAllowed(address,bool)" \
  $ROUTER_ADDRESS true \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL

Step 5: Update Miniapp Configuration

After deployment, update apps/miniapp/.env.local with your deployed addresses:

# Base Mainnet (chainId: 8453)
NEXT_PUBLIC_FACTORY_ADDRESS_8453=0xYourFactoryAddress
NEXT_PUBLIC_ROUTER_ADDRESS_8453=0xYourRouterAddress

# RPC Configuration (if not already set)
NEXT_PUBLIC_BASE_RPC_URL=https://mainnet.base.org
# Or use your own RPC endpoint:
# NEXT_PUBLIC_BASE_RPC_URL=https://base-mainnet.g.alchemy.com/v2/YOUR_API_KEY

# IPFS Configuration (optional)
NEXT_PUBLIC_IPFS_URL=https://ipfs.io

Important: Restart your Next.js dev server after updating .env.local for changes to take effect.

Step 6: Test the Deployment

  1. Create a test pool: Use the factory to create a test ERC721 pool
  2. Verify pool appears: Check that the pool appears in the browse page at /browse/[nftContractAddress]
  3. Test buying: Try buying an NFT from the pool
  4. Test selling: Try selling an NFT to the pool

Troubleshooting

"Bonding curve not whitelisted" error

  • Make sure you've whitelisted all 4 sudoswap bonding curves
  • Verify the addresses are correct (use Base Mainnet addresses, not Ethereum Mainnet)
  • If you accidentally whitelisted Ethereum addresses, use fix-base-bonding-curves.sh to fix it

"Router not whitelisted" error

  • Make sure you've whitelisted your router address in the factory
  • Verify the router address is correct

Factory owner mismatch

  • If auto-configuration was skipped, manually configure using Step 4
  • Make sure you're using the factory owner's private key

Contracts not verified on BaseScan

  • Make sure ETHERSCAN_API_KEY is set correctly
  • BaseScan uses the same API as Etherscan
  • You can verify manually later if needed

Notes

  • Bonding curves: The sudoswap bonding curves are deployed separately on Base Mainnet. Use the Base Mainnet addresses, not Ethereum Mainnet addresses.
  • Fee collection: Your factory will collect protocol fees according to PROTOCOL_FEE_MULTIPLIER and send them to PROTOCOL_FEE_RECIPIENT.
  • Factory ownership: The FACTORY_OWNER address has full control over the factory, including fee updates and whitelisting.

Next Steps

After deployment:

  1. Update the miniapp environment variables
  2. Test pool creation and trading
  3. Monitor fee collection
  4. Consider setting up a subgraph for better pool discovery performance (see FUTURE_INDEXING.md)
Deploy to Base Testnet

Base Sepolia Testnet Deployment Guide

This guide walks you through deploying your own factory, router, and bonding curve contracts to Base Sepolia testnet.

Prerequisites

  1. Foundry installed: forge --version should work
  2. Base Sepolia RPC: Get an RPC endpoint (Alchemy, Infura, or public)
  3. Testnet account: Account with testnet ETH for gas fees
  4. Environment variables: Set up in .env.local (see below)

Step 1: Set Up Environment Variables

Create packages/lssvm-contracts/.env.local with the following:

# Network Configuration (Base Sepolia Testnet)
RPC_URL=https://sepolia.base.org
# Or use your own RPC endpoint:
# RPC_URL=https://base-sepolia.g.alchemy.com/v2/YOUR_API_KEY

# Deployment Account
PRIVATE_KEY=your_private_key_here
# Or use a mnemonic (will use index 2 by default):
# MNEMONIC="your twelve word seed phrase here"
# MNEMONIC_INDEX=2

# Contract Verification (optional but recommended)
ETHERSCAN_API_KEY=your_base_scan_api_key_here

# Contract Configuration
# Manifold Royalty Registry for Base Sepolia
# Check https://docs.manifold.xyz/v/manifold-for-developers/contract-docs/royalty-registry
# For testnet, you may need to deploy your own or use a testnet-specific address
ROYALTY_REGISTRY=0x0000000000000000000000000000000000000000

# Protocol Fee Configuration
PROTOCOL_FEE_RECIPIENT=0x0000000000000000000000000000000000000000
PROTOCOL_FEE_MULTIPLIER=10000000000000000  # 1% (0.01 * 1e18)

# Factory Owner (defaults to deployer address if not set)
FACTORY_OWNER=0x0000000000000000000000000000000000000000

# Bonding Curves (optional)
# Set to false to use existing bonding curve addresses
DEPLOY_BONDING_CURVES=true
# If DEPLOY_BONDING_CURVES=false, provide existing addresses:
# LINEAR_CURVE_ADDRESS=0x...
# EXPONENTIAL_CURVE_ADDRESS=0x...
# XYK_CURVE_ADDRESS=0x...
# GDA_CURVE_ADDRESS=0x...

Step 2: Get Testnet ETH

You'll need testnet ETH for gas fees. Get it from:

  • Coinbase Base Sepolia Faucet: https://www.coinbase.com/faucets/base-ethereum-goerli-faucet
  • Base Bridge: https://bridge.base.org/deposit (bridge from Goerli/Sepolia)
  • Base Sepolia Faucet: https://www.coinbase.com/faucets/base-ethereum-goerli-faucet

Verify your balance:

cast balance YOUR_ADDRESS --rpc-url $RPC_URL

Step 3: Deploy Contracts

Run the deployment script:

cd packages/lssvm-contracts
./deploy-base-testnet.sh

The script will:

  1. Deploy bonding curves (LinearCurve, ExponentialCurve, XykCurve, GDACurve)
  2. Deploy RoyaltyEngine
  3. Deploy pair templates (ERC721ETH, ERC721ERC20, ERC1155ETH, ERC1155ERC20)
  4. Deploy LSSVMPairFactory
  5. Deploy VeryFastRouter
  6. Configure factory (whitelist bonding curves and router)
  7. Verify contracts on BaseScan Sepolia (if ETHERSCAN_API_KEY is set)

Step 4: Verify Deployment

After deployment, verify the contracts are working:

# Set your addresses
FACTORY_ADDRESS=0x...
ROUTER_ADDRESS=0x...

# Check factory owner
cast call $FACTORY_ADDRESS "owner()" --rpc-url $RPC_URL

# Check protocol fee recipient
cast call $FACTORY_ADDRESS "protocolFeeRecipient()" --rpc-url $RPC_URL

Verify bonding curves are whitelisted:

# Get bonding curve addresses from deployment output
LINEAR_CURVE=0x...
EXPONENTIAL_CURVE=0x...
XYK_CURVE=0x...
GDA_CURVE=0x...

cast call $FACTORY_ADDRESS "bondingCurveAllowed(address)" $LINEAR_CURVE --rpc-url $RPC_URL
cast call $FACTORY_ADDRESS "bondingCurveAllowed(address)" $EXPONENTIAL_CURVE --rpc-url $RPC_URL
cast call $FACTORY_ADDRESS "bondingCurveAllowed(address)" $XYK_CURVE --rpc-url $RPC_URL
cast call $FACTORY_ADDRESS "bondingCurveAllowed(address)" $GDA_CURVE --rpc-url $RPC_URL

Verify router is whitelisted:

# Replace ROUTER_ADDRESS with the actual address from deployment
cast call $FACTORY_ADDRESS "routerStatus(address)" $ROUTER_ADDRESS --rpc-url $RPC_URL
# Should return 0x...0001 (true) for the first 66 characters

Step 5: Update Miniapp Configuration

Update apps/miniapp/.env.local with your deployed addresses:

# Base Sepolia Testnet (chainId: 84532)
NEXT_PUBLIC_FACTORY_ADDRESS_84532=0x...
NEXT_PUBLIC_ROUTER_ADDRESS_84532=0x...

# Base Sepolia RPC (optional, for better rate limits)
NEXT_PUBLIC_BASE_SEPOLIA_RPC_URL=https://base-sepolia.g.alchemy.com/v2/YOUR_API_KEY

Restart your Next.js dev server for changes to take effect.

Manual Configuration (if needed)

If the deployer is not the factory owner, you'll need to configure manually:

# Set your addresses
FACTORY_ADDRESS=0x...
ROUTER_ADDRESS=0x...
LINEAR_CURVE=0x...
EXPONENTIAL_CURVE=0x...
XYK_CURVE=0x...
GDA_CURVE=0x...
PRIVATE_KEY=your_private_key
RPC_URL=https://sepolia.base.org

# Whitelist bonding curves (Base Sepolia addresses)
cast send $FACTORY_ADDRESS \
  "setBondingCurveAllowed(address,bool)" \
  $LINEAR_CURVE true \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL

cast send $FACTORY_ADDRESS \
  "setBondingCurveAllowed(address,bool)" \
  $EXPONENTIAL_CURVE true \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL

cast send $FACTORY_ADDRESS \
  "setBondingCurveAllowed(address,bool)" \
  $XYK_CURVE true \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL

cast send $FACTORY_ADDRESS \
  "setBondingCurveAllowed(address,bool)" \
  $GDA_CURVE true \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL

# Whitelist router
cast send $FACTORY_ADDRESS \
  "setRouterAllowed(address,bool)" \
  $ROUTER_ADDRESS true \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL

Testing Your Deployment

  1. Create a test pool: Use the factory to create a new NFT pool
  2. Test buying: Try buying an NFT from the pool
  3. Test selling: Try selling an NFT to the pool

Troubleshooting

"Bonding curve not whitelisted" error

  • Make sure you've whitelisted all 4 bonding curves
  • Verify the addresses are correct (check deployment output)

"Router not whitelisted" error

  • Make sure you've whitelisted your router address in the factory
  • Verify the router address is correct

"Insufficient funds" error

  • Get more testnet ETH from the faucet
  • Check your balance: cast balance YOUR_ADDRESS --rpc-url $RPC_URL

Contracts not verified on BaseScan

  • Make sure ETHERSCAN_API_KEY is set correctly
  • BaseScan Sepolia uses the same API as Etherscan
  • You can verify manually later if needed

Notes

  • Bonding curves: By default, the script deploys new bonding curves. Set DEPLOY_BONDING_CURVES=false to use existing ones.
  • Fee collection: Your factory will collect protocol fees according to PROTOCOL_FEE_MULTIPLIER and send them to PROTOCOL_FEE_RECIPIENT.
  • Factory ownership: The FACTORY_OWNER address has full control over the factory, including fee updates and whitelisting.
  • Testnet vs Mainnet: This deployment is for Base Sepolia testnet (chain ID 84532). For mainnet, use deploy-base.sh.

Next Steps

After deployment:

  1. Update the miniapp environment variables
  2. Test creating pools and trading NFTs
  3. Verify contracts on BaseScan Sepolia
  4. When ready for mainnet, follow the Base Mainnet Deployment Guide

Resources

  • Base Sepolia Explorer: https://sepolia.basescan.org
  • Base Sepolia RPC: https://sepolia.base.org
  • Base Documentation: https://docs.base.org
  • Base Faucet: https://www.coinbase.com/faucets/base-ethereum-goerli-faucet
Deployment Improvements

Deployment Script Improvements

This document explains the improvements made to the deployment scripts and local testing setup.

Changes Made

1. Fixed Factory Auto-Configuration (DeployAll.s.sol)

Problem: The factory configuration check was using msg.sender, which doesn't reliably match the deployer address in Foundry scripts, causing auto-configuration to be skipped even when the deployer was the factory owner.

Solution: Updated configureFactory() function to:

  • Use tx.origin instead of msg.sender for deployer detection
  • Add fallback check: verify the factory's actual owner matches FACTORY_OWNER
  • Proceed with configuration if either check passes
  • Provide detailed logging when configuration is skipped

Best Practice:

  • Always verify the actual contract state rather than relying solely on msg.sender
  • Use tx.origin for deployer detection in deployment scripts
  • Add fallback checks for critical operations

Code Location: script/DeployAll.s.sol, lines 200-226

2. Added Sender Flag Support (deploy-local.sh)

Problem: Foundry was warning about using the default sender, which could cause confusion about which address is deploying contracts.

Solution:

  • Extract deployer address from PRIVATE_KEY using cast wallet address
  • Automatically add --sender flag to forge script command
  • Gracefully handle cases where address extraction fails

Best Practice:

  • Always explicitly specify the sender address when deploying
  • Derive addresses from private keys programmatically for consistency
  • Provide fallback behavior when address extraction fails

Code Location: deploy-local.sh, lines 31-39

3. Created Comprehensive Local Testing Guide (LOCAL_TESTING.md)

Purpose: Provide step-by-step instructions for testing the protocol locally.

Contents:

  • Prerequisites and setup
  • Deployment instructions
  • Factory configuration (automatic and manual)
  • Complete ERC721 pool testing workflow
  • Complete ERC1155 pool testing workflow
  • Useful cast commands for querying contracts
  • Troubleshooting guide

Best Practice:

  • Document all testing workflows comprehensively
  • Include both automatic and manual configuration paths
  • Provide copy-paste ready commands with placeholders
  • Include troubleshooting for common issues

File: LOCAL_TESTING.md

4. Updated README with Reference (script/README.md)

Change: Added reference to the comprehensive local testing guide at the beginning of the Local Testing section.

Best Practice:

  • Keep README concise, link to detailed guides
  • Provide overview of what's covered in linked documents

Best Practices Implemented

1. Deployer Detection

Why: In Foundry scripts, msg.sender may not reliably represent the deployer address, especially when using vm.startBroadcast().

Implementation:

address deployer = tx.origin; // More reliable for deployer detection
address actualOwner = factory.owner(); // Verify actual state
bool shouldConfigure = (deployer == factoryOwner) || (actualOwner == factoryOwner);

Rationale:

  • tx.origin represents the original transaction sender
  • Checking actual contract state provides a fallback
  • Both checks ensure configuration works in various scenarios

2. Explicit Sender Specification

Why: Foundry recommends explicitly setting the sender to avoid confusion and ensure transactions are sent from the expected address.

Implementation:

DEPLOYER_ADDRESS=$(cast wallet address $PRIVATE_KEY)
forge script ... --sender $DEPLOYER_ADDRESS

Rationale:

  • Eliminates Foundry warnings
  • Makes it clear which address is deploying
  • Ensures consistency across deployments

3. Comprehensive Documentation

Why: Local testing requires many steps and commands. Having everything in one place reduces errors and speeds up testing.

Implementation:

  • Single comprehensive guide (LOCAL_TESTING.md)
  • Step-by-step instructions for each workflow
  • Copy-paste ready commands with clear placeholders
  • Troubleshooting section for common issues

Rationale:

  • Reduces time to get started
  • Prevents common mistakes
  • Makes testing accessible to developers at all levels

4. Graceful Error Handling

Why: Scripts should handle edge cases gracefully rather than failing silently or with unclear errors.

Implementation:

  • Fallback checks in factory configuration
  • Detailed logging when configuration is skipped
  • Graceful handling of missing address extraction

Rationale:

  • Better developer experience
  • Easier debugging
  • More reliable deployments

Testing the Improvements

Verify Auto-Configuration Works

  1. Deploy using the helper script:

    ./deploy-local.sh
    
  2. Check logs for "Configuration complete!" message

  3. Verify bonding curves are whitelisted:

    cast call $FACTORY_ADDRESS \
      "bondingCurveAllowed(address)" \
      $LINEAR_CURVE \
      --rpc-url http://127.0.0.1:8545
    

Verify Sender Flag

The deployment script should no longer show the "default sender" warning. Check the output for:

  • "Deployer address: 0x..." message
  • No "You seem to be using Foundry's default sender" error

Test Local Testing Guide

Follow the guide in LOCAL_TESTING.md to:

  1. Deploy contracts
  2. Configure factory (if needed)
  3. Create and test ERC721 pool
  4. Create and test ERC1155 pool

Future Improvements

Potential enhancements for future iterations:

  1. Automated Testing Script: Create a script that runs through all test scenarios automatically
  2. Deployment Verification: Add automatic verification of all deployed contracts
  3. Gas Reporting: Include gas usage reports in deployment output
  4. Multi-Network Support: Extend scripts to support multiple testnets easily
  5. Interactive Mode: Add interactive prompts for missing configuration

References

Deployment Scripts

sudoAMM v2 Deployment Guide

This directory contains deployment scripts for the sudoAMM v2 protocol. The scripts are organized to deploy contracts in the correct dependency order.

Table of Contents

Overview

The sudoAMM v2 protocol consists of several components that must be deployed in a specific order due to dependencies between contracts. The deployment can be done either:

  1. All at once using DeployAll.s.sol (recommended for testing/development)
  2. Step by step using individual scripts (recommended for production)

Prerequisites

  • Foundry installed
  • RPC endpoint for target network
  • Private key or mnemonic for deployment account
  • Sufficient native token (ETH/MATIC/etc.) for gas fees
  • Etherscan API key (optional, for contract verification)

Deployment Order

The contracts must be deployed in the following order:

1. RoyaltyEngine
   └── Requires: Manifold Royalty Registry address (external)

2. Pair Templates (all require RoyaltyEngine)
   ├── LSSVMPairERC721ETH
   ├── LSSVMPairERC721ERC20
   ├── LSSVMPairERC1155ETH
   └── LSSVMPairERC1155ERC20

3. LSSVMPairFactory
   └── Requires: All 4 pair templates

4. Bonding Curves (independent)
   ├── LinearCurve
   ├── ExponentialCurve
   ├── XykCurve
   └── GDACurve

5. VeryFastRouter
   └── Requires: LSSVMPairFactory

6. Property Checker Templates (independent)
   ├── MerklePropertyChecker
   └── RangePropertyChecker

7. PropertyCheckerFactory
   └── Requires: Property checker templates

8. Settings Components
   ├── Splitter (independent)
   ├── StandardSettings (requires Splitter + Factory)
   └── StandardSettingsFactory (requires StandardSettings)

Environment Variables

Create a .env file in the project root with the following variables:

# Network Configuration
RPC_URL=<your_rpc_url>
ETHERSCAN_API_KEY=<your_etherscan_api_key>

# Deployment Account
PRIVATE_KEY=<your_private_key>
# OR
MNEMONIC=<your_mnemonic>

# Contract Configuration
ROYALTY_REGISTRY=<manifold_royalty_registry_address>
PROTOCOL_FEE_RECIPIENT=<address_to_receive_fees>
PROTOCOL_FEE_MULTIPLIER=<fee_in_1e18_basis_max_0.1e18>
FACTORY_OWNER=<address_that_will_own_factory>

Configuration Details

ROYALTY_REGISTRY: Address of the Manifold Royalty Registry for your network

PROTOCOL_FEE_RECIPIENT: Address that will receive protocol trading fees

PROTOCOL_FEE_MULTIPLIER: Protocol fee as a multiplier in base 1e18

  • Example: 0.01e18 = 1%, 0.05e18 = 5%
  • Maximum: 0.1e18 (10%)

FACTORY_OWNER: Address that will have ownership of the factory contract

  • Can whitelist bonding curves
  • Can whitelist routers
  • Can update protocol fees
  • Can enable settings for collections

Deployment Scripts

Individual Scripts

| Script | Purpose | Dependencies | |--------|---------|--------------| | 01_DeployCore.s.sol | Deploy core contracts (RoyaltyEngine, Templates, Factory) | ROYALTY_REGISTRY | | 02_DeployBondingCurves.s.sol | Deploy all bonding curve contracts | None | | 03_DeployRouter.s.sol | Deploy VeryFastRouter | FACTORY_ADDRESS | | 04_DeployPropertyCheckers.s.sol | Deploy property checker system | None | | 05_DeploySettings.s.sol | Deploy settings system | FACTORY_ADDRESS |

Master Script

| Script | Purpose | |--------|---------| | DeployAll.s.sol | Deploy entire protocol in one go |

Usage

Option 1: Deploy All Contracts at Once

This is the simplest approach for development/testing:

# 1. Set up environment variables
cp .env.example .env
# Edit .env with your values

# 2. Load environment variables
source .env

# 3. Deploy all contracts
forge script script/DeployAll.s.sol:DeployAll \
  --rpc-url $RPC_URL \
  --broadcast \
  --verify \
  -vvvv

Option 2: Step-by-Step Deployment

This approach gives more control and is recommended for production:

# Load environment variables
source .env

# Step 1: Deploy core contracts
forge script script/01_DeployCore.s.sol:DeployCore \
  --rpc-url $RPC_URL \
  --broadcast \
  --verify \
  -vvvv

# Save the FACTORY_ADDRESS from output and add to .env
export FACTORY_ADDRESS=<factory_address_from_step_1>

# Step 2: Deploy bonding curves
forge script script/02_DeployBondingCurves.s.sol:DeployBondingCurves \
  --rpc-url $RPC_URL \
  --broadcast \
  --verify \
  -vvvv

# Step 3: Deploy router
forge script script/03_DeployRouter.s.sol:DeployRouter \
  --rpc-url $RPC_URL \
  --broadcast \
  --verify \
  -vvvv

# Step 4: Deploy property checkers
forge script script/04_DeployPropertyCheckers.s.sol:DeployPropertyCheckers \
  --rpc-url $RPC_URL \
  --broadcast \
  --verify \
  -vvvv

# Step 5: Deploy settings
forge script script/05_DeploySettings.s.sol:DeploySettings \
  --rpc-url $RPC_URL \
  --broadcast \
  --verify \
  -vvvv

Dry Run (Simulation)

Before broadcasting transactions, you can simulate the deployment:

# Simulate without --broadcast flag
forge script script/DeployAll.s.sol:DeployAll \
  --rpc-url $RPC_URL \
  -vvvv

Local Testing

Before deploying to testnet or mainnet, it's highly recommended to test deployments locally. This helps catch configuration errors and ensures everything works as expected.

📖 For comprehensive local testing instructions, see LOCAL_TESTING.md

The guide covers:

  • Complete deployment workflow
  • Factory configuration (automatic and manual)
  • Testing ERC721 pools (create, buy, sell)
  • Testing ERC1155 pools (create, buy, sell)
  • Useful cast commands for querying contracts
  • Troubleshooting common issues

Option 1: Local Anvil Node (Recommended for First-Time Testing)

Anvil is Foundry's local Ethereum node. It's perfect for testing deployments without any external dependencies:

# Terminal 1: Start Anvil (local node)
anvil

# This will output something like:
# Available Accounts
# ==================
# (0) 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000 ETH)
# ...
# Private Keys
# ==================
# (0) 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
# ...
# RPC URL: http://127.0.0.1:8545

Create a .env.local file for local testing:

# .env.local
RPC_URL=http://127.0.0.1:8545
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

# For local testing, you can use any address - RoyaltyEngine will fallback gracefully
# Option 1: Use address(0) - royalties won't work but deployment will succeed
ROYALTY_REGISTRY=0x0000000000000000000000000000000000000000

# Option 2: Deploy a mock registry (see test files for examples)
# Option 3: Use a real testnet address if you're forking

# Use the first Anvil account for everything
PROTOCOL_FEE_RECIPIENT=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
PROTOCOL_FEE_MULTIPLIER=10000000000000000  # 0.01e18 = 1%
FACTORY_OWNER=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266

Note: The RoyaltyEngine contract accepts any address. If the registry call fails, it gracefully falls back to using the token address itself for ERC2981 lookups. For local testing without royalties, address(0) works fine.

# Terminal 2: Deploy to local Anvil node
cd packages/lssvm-contracts
source .env.local

# Deploy all contracts
forge script script/DeployAll.s.sol:DeployAll \
  --rpc-url $RPC_URL \
  --broadcast \
  -vvvv

After deployment, you can interact with the contracts using cast:

# Check factory owner
cast call <FACTORY_ADDRESS> "owner()" --rpc-url http://127.0.0.1:8545

# Check protocol fee recipient
cast call <FACTORY_ADDRESS> "protocolFeeRecipient()" --rpc-url http://127.0.0.1:8545

Option 2: Forked Testnet (More Realistic)

For more realistic testing, you can fork a testnet (like Base Sepolia) and deploy to the fork:

# Start Anvil with a testnet fork
anvil --fork-url https://sepolia.base.org

# Or fork Ethereum Sepolia
anvil --fork-url https://eth-sepolia.g.alchemy.com/v2/YOUR_API_KEY

This gives you:

  • Real contract addresses (like the Manifold Royalty Registry)
  • Real token addresses if you want to test with actual NFTs
  • More realistic gas costs and behavior

Use the same deployment commands as Option 1, but with testnet addresses in your .env.local:

# .env.local for forked testnet
RPC_URL=http://127.0.0.1:8545
PRIVATE_KEY=<your_test_account_private_key>

# Use real testnet addresses (check Network-Specific Addresses section for testnet registry addresses)
ROYALTY_REGISTRY=0x0000000000000000000000000000000000000000  # Replace with actual testnet registry
PROTOCOL_FEE_RECIPIENT=<your_address>
PROTOCOL_FEE_MULTIPLIER=10000000000000000
FACTORY_OWNER=<your_address>

Testing Checklist

After local deployment, verify:

  1. Factory Deployment

    cast call $FACTORY_ADDRESS "owner()" --rpc-url $RPC_URL
    # Should return your FACTORY_OWNER address
    
  2. Bonding Curves Whitelisted

    cast call $FACTORY_ADDRESS "bondingCurveAllowed(address)" $LINEAR_CURVE --rpc-url $RPC_URL
    # Should return 0x0000000000000000000000000000000000000000000000000000000000000001 (true)
    
  3. Router Whitelisted

    cast call $FACTORY_ADDRESS "routerAllowed(address)" $ROUTER_ADDRESS --rpc-url $RPC_URL
    # Should return true
    
  4. Create a Test Pool (if you have test NFTs)

    • Use the factory to create a test pool
    • Verify the pool was created correctly

Troubleshooting Local Deployments

Issue: "execution reverted" errors

  • Solution: Check that all environment variables are set correctly, especially addresses are valid

Issue: "insufficient funds"

  • Solution: Anvil accounts start with 10000 ETH, but if using a fork, ensure your account has funds

Issue: "ROYALTY_REGISTRY not found"

  • Solution: For local testing without a fork, you may need to deploy a mock royalty registry or use a valid address format

Post-Deployment Configuration

After deployment, the following configuration steps must be performed by the factory owner:

1. Whitelist Bonding Curves

The bonding curves must be whitelisted in the factory to be usable:

// Call these on LSSVMPairFactory
factory.setBondingCurveAllowed(linearCurveAddress, true);
factory.setBondingCurveAllowed(exponentialCurveAddress, true);
factory.setBondingCurveAllowed(xykCurveAddress, true);
factory.setBondingCurveAllowed(gdaCurveAddress, true);

2. Whitelist Router

The VeryFastRouter must be whitelisted to interact with pairs:

factory.setRouterAllowed(veryFastRouterAddress, true);

3. (Optional) Enable Call Targets

If you want to allow specific contracts to be called by pairs:

factory.setCallAllowed(targetAddress, true);

Note: The DeployAll.s.sol script automatically performs steps 1 and 2 if the deployer is the factory owner.

Network-Specific Addresses

Manifold Royalty Registry Addresses

| Network | Address | |---------|---------| | Ethereum Mainnet | 0xad2184fb5dbcfc05d8f056542fb25b04fa32a95d | | Goerli | 0xe7c9cb6d966f76f3b5142167088927bf34966a1f | | Polygon | 0x28EdFcF0Be7E86b07493466e7631a213bDe8eEF2 | | Arbitrum | 0xEf96021Af16BD04918b0d87cE045d7984ad6c38c | | Optimism | 0xad2184fb5dbcfc05d8f056542fb25b04fa32a95d |

For other networks, check the Manifold Royalty Registry documentation.

Manifold Royalty System Addresses (Universal)

The following addresses are consistent across Base and all EVM chains:

| Contract | Address | |----------|---------| | TimeLock Controller | 0xe3A6CD067a1193b903143C36dA00557c9d95C41e | | Royalty Registry Impl | 0xd389340d95c851655dD99c5781be1c5e39d30B31 | | Royalty Engine Impl | 0xD388d812c1cE2CE7C46D797684BA912De65CD414 | | Royalty Override Factory | 0x103247393F448203ed7Ff7515E262316812637B4 | | Royalty Fallback Registry | 0xB78fC2052717C7AE061a14dB1fB2038d5AC34D29 |

sudoAMM v2 Production Deployments

The following are the official sudoAMM v2 deployments on Ethereum Mainnet:

Core Contracts:

  • LSSVMPairFactory: 0xA020d57aB0448Ef74115c112D18a9C231CC86000
  • VeryFastRouter: 0x090C236B62317db226e6ae6CD4c0Fd25b7028b65

Bonding Curves:

  • LinearCurve: 0xe5d78fec1a7f42d2F3620238C498F088A866FdC5
  • ExponentialCurve: 0xfa056C602aD0C0C4EE4385b3233f2Cb06730334a
  • XYKCurve: 0xc7fB91B6cd3C67E02EC08013CEBb29b1241f3De5
  • GDACurve: 0x1fD5876d4A3860Eb0159055a3b7Cb79fdFFf6B67

Other:

  • SettingsFactory: 0xF4F439A6A152cFEcb1F34d726D490F82Bcb3c2C7
  • PropertyCheckerFactory: 0x031b216FaBec82310FEa3426b33455609b99AfC1
  • RoyaltyEngine: 0xBc40d21999b4BF120d330Ee3a2DE415287f626C9

Testing Deployments

After deployment, verify the contracts are working correctly:

1. Verify Contract Deployment

# Check factory owner
cast call $FACTORY_ADDRESS "owner()" --rpc-url $RPC_URL

# Check protocol fee recipient
cast call $FACTORY_ADDRESS "protocolFeeRecipient()" --rpc-url $RPC_URL

# Check if a curve is whitelisted
cast call $FACTORY_ADDRESS "bondingCurveAllowed(address)" $LINEAR_CURVE --rpc-url $RPC_URL

2. Create a Test Pool

# You can use the factory to create a test pool
# See the main documentation for pool creation examples

Troubleshooting

Common Issues

Issue: "Insufficient funds for gas"

  • Solution: Ensure your deployment account has enough native tokens

Issue: "Nonce too low"

  • Solution: Wait for previous transactions to confirm, or manually set nonce

Issue: "Contract verification failed"

  • Solution: Ensure ETHERSCAN_API_KEY is correct and wait a few minutes before retrying

Issue: "Factory owner mismatch"

  • Solution: Ensure FACTORY_OWNER matches your deployment account if you want automatic configuration

Advanced Usage

Using a Hardware Wallet

forge script script/DeployAll.s.sol:DeployAll \
  --rpc-url $RPC_URL \
  --ledger \
  --sender $YOUR_ADDRESS \
  --broadcast

Using a Mnemonic

forge script script/DeployAll.s.sol:DeployAll \
  --rpc-url $RPC_URL \
  --mnemonic-path .mnemonic \
  --broadcast

Deploying to a Fork

# Start a local fork
anvil --fork-url $RPC_URL

# Deploy to the fork
forge script script/DeployAll.s.sol:DeployAll \
  --rpc-url http://localhost:8545 \
  --broadcast

Security Considerations

  1. Private Key Security: Never commit private keys or mnemonics to version control
  2. Verify Contracts: Always verify contracts on block explorers after deployment
  3. Multi-sig Ownership: Consider using a multi-sig wallet as the factory owner
  4. Test First: Deploy to a testnet before mainnet
  5. Audit: Ensure all contracts are audited before production deployment

Support

For questions or issues:

  • Documentation: https://docs.sudoswap.xyz/
  • GitHub Issues: https://github.com/sudoswap/lssvm2/issues
  • Discord: https://discord.gg/sudoswap

License

All deployment scripts are licensed under AGPL-3.0, matching the protocol license.

Deployment Checklist

sudoAMM v2 Deployment Checklist

Use this checklist to ensure a complete and correct deployment of the sudoAMM v2 protocol.

Pre-Deployment

  • [ ] Install Foundry (curl -L https://foundry.paradigm.xyz | bash && foundryup)
  • [ ] Clone the repository
  • [ ] Run forge install to install dependencies
  • [ ] Run forge build to ensure contracts compile
  • [ ] Run forge test to ensure all tests pass
  • [ ] Copy script/.env.example to script/.env or project root .env
  • [ ] Configure all environment variables in .env:
    • [ ] RPC_URL - RPC endpoint for target network
    • [ ] ETHERSCAN_API_KEY - API key for contract verification
    • [ ] PRIVATE_KEY or MNEMONIC - Deployment account credentials
    • [ ] ROYALTY_REGISTRY - Manifold Royalty Registry address for your network
    • [ ] PROTOCOL_FEE_RECIPIENT - Address to receive protocol fees
    • [ ] PROTOCOL_FEE_MULTIPLIER - Fee multiplier (max 0.1e18 = 10%)
    • [ ] FACTORY_OWNER - Address to own the factory
  • [ ] Ensure deployment account has sufficient funds for gas
  • [ ] Review security considerations in README.md

Deployment (Option 1: All at Once)

  • [ ] Run simulation: forge script script/DeployAll.s.sol:DeployAll --rpc-url $RPC_URL -vvvv
  • [ ] Review simulation output for errors
  • [ ] Deploy: forge script script/DeployAll.s.sol:DeployAll --rpc-url $RPC_URL --broadcast --verify -vvvv
  • [ ] Save all deployed contract addresses from output
  • [ ] Verify automatic configuration completed (if deployer is factory owner)

Deployment (Option 2: Step by Step)

Step 1: Core Contracts

  • [ ] Run: forge script script/01_DeployCore.s.sol:DeployCore --rpc-url $RPC_URL --broadcast --verify -vvvv
  • [ ] Record deployed addresses:
    • [ ] RoyaltyEngine: ___________________________________
    • [ ] LSSVMPairERC721ETH: ___________________________________
    • [ ] LSSVMPairERC721ERC20: ___________________________________
    • [ ] LSSVMPairERC1155ETH: ___________________________________
    • [ ] LSSVMPairERC1155ERC20: ___________________________________
    • [ ] LSSVMPairFactory: ___________________________________
  • [ ] Add FACTORY_ADDRESS to .env file

Step 2: Bonding Curves

  • [ ] Run: forge script script/02_DeployBondingCurves.s.sol:DeployBondingCurves --rpc-url $RPC_URL --broadcast --verify -vvvv
  • [ ] Record deployed addresses:
    • [ ] LinearCurve: ___________________________________
    • [ ] ExponentialCurve: ___________________________________
    • [ ] XykCurve: ___________________________________
    • [ ] GDACurve: ___________________________________

Step 3: Router

  • [ ] Run: forge script script/03_DeployRouter.s.sol:DeployRouter --rpc-url $RPC_URL --broadcast --verify -vvvv
  • [ ] Record deployed address:
    • [ ] VeryFastRouter: ___________________________________

Step 4: Property Checkers

  • [ ] Run: forge script script/04_DeployPropertyCheckers.s.sol:DeployPropertyCheckers --rpc-url $RPC_URL --broadcast --verify -vvvv
  • [ ] Record deployed addresses:
    • [ ] MerklePropertyChecker: ___________________________________
    • [ ] RangePropertyChecker: ___________________________________
    • [ ] PropertyCheckerFactory: ___________________________________

Step 5: Settings

  • [ ] Run: forge script script/05_DeploySettings.s.sol:DeploySettings --rpc-url $RPC_URL --broadcast --verify -vvvv
  • [ ] Record deployed addresses:
    • [ ] Splitter: ___________________________________
    • [ ] StandardSettings: ___________________________________
    • [ ] StandardSettingsFactory: ___________________________________

Post-Deployment Configuration

Whitelist Bonding Curves

  • [ ] Whitelist LinearCurve: cast send $FACTORY_ADDRESS "setBondingCurveAllowed(address,bool)" $LINEAR_CURVE true --rpc-url $RPC_URL --private-key $PRIVATE_KEY
  • [ ] Whitelist ExponentialCurve: cast send $FACTORY_ADDRESS "setBondingCurveAllowed(address,bool)" $EXPONENTIAL_CURVE true --rpc-url $RPC_URL --private-key $PRIVATE_KEY
  • [ ] Whitelist XykCurve: cast send $FACTORY_ADDRESS "setBondingCurveAllowed(address,bool)" $XYK_CURVE true --rpc-url $RPC_URL --private-key $PRIVATE_KEY
  • [ ] Whitelist GDACurve: cast send $FACTORY_ADDRESS "setBondingCurveAllowed(address,bool)" $GDA_CURVE true --rpc-url $RPC_URL --private-key $PRIVATE_KEY

Whitelist Router

  • [ ] Whitelist VeryFastRouter: cast send $FACTORY_ADDRESS "setRouterAllowed(address,bool)" $ROUTER_ADDRESS true --rpc-url $RPC_URL --private-key $PRIVATE_KEY

Optional: Whitelist Call Targets

  • [ ] Identify any contracts that should be callable by pairs
  • [ ] Whitelist each: cast send $FACTORY_ADDRESS "setCallAllowed(address,bool)" $TARGET_ADDRESS true --rpc-url $RPC_URL --private-key $PRIVATE_KEY

Verification

Contract Verification on Block Explorer

  • [ ] Verify RoyaltyEngine is verified on Etherscan
  • [ ] Verify all pair templates are verified on Etherscan
  • [ ] Verify LSSVMPairFactory is verified on Etherscan
  • [ ] Verify all bonding curves are verified on Etherscan
  • [ ] Verify VeryFastRouter is verified on Etherscan
  • [ ] Verify property checker contracts are verified on Etherscan
  • [ ] Verify settings contracts are verified on Etherscan

Functional Verification

  • [ ] Verify factory owner: cast call $FACTORY_ADDRESS "owner()" --rpc-url $RPC_URL
  • [ ] Verify protocol fee recipient: cast call $FACTORY_ADDRESS "protocolFeeRecipient()" --rpc-url $RPC_URL
  • [ ] Verify protocol fee multiplier: cast call $FACTORY_ADDRESS "protocolFeeMultiplier()" --rpc-url $RPC_URL
  • [ ] Verify LinearCurve is whitelisted: cast call $FACTORY_ADDRESS "bondingCurveAllowed(address)" $LINEAR_CURVE --rpc-url $RPC_URL
  • [ ] Verify ExponentialCurve is whitelisted: cast call $FACTORY_ADDRESS "bondingCurveAllowed(address)" $EXPONENTIAL_CURVE --rpc-url $RPC_URL
  • [ ] Verify XykCurve is whitelisted: cast call $FACTORY_ADDRESS "bondingCurveAllowed(address)" $XYK_CURVE --rpc-url $RPC_URL
  • [ ] Verify GDACurve is whitelisted: cast call $FACTORY_ADDRESS "bondingCurveAllowed(address)" $GDA_CURVE --rpc-url $RPC_URL
  • [ ] Verify VeryFastRouter is whitelisted: cast call $FACTORY_ADDRESS "routerStatus(address)" $ROUTER_ADDRESS --rpc-url $RPC_URL

Test Pool Creation (Optional)

  • [ ] Create a test ERC721-ETH pool using the factory
  • [ ] Verify the pool was created successfully
  • [ ] Test a swap on the pool (if applicable)

Documentation

  • [ ] Document all deployed contract addresses in a deployment record file
  • [ ] Update any internal documentation with new addresses
  • [ ] Notify relevant stakeholders of deployment completion
  • [ ] Share block explorer links for all contracts

Security

  • [ ] Transfer factory ownership to multi-sig (if applicable): cast send $FACTORY_ADDRESS "transferOwnership(address)" $MULTISIG_ADDRESS --rpc-url $RPC_URL --private-key $PRIVATE_KEY
  • [ ] Verify ownership transfer: cast call $FACTORY_ADDRESS "owner()" --rpc-url $RPC_URL
  • [ ] Securely backup all deployment information
  • [ ] Remove private keys from environment variables
  • [ ] Delete any local copies of private keys used for deployment

Mainnet-Specific (if deploying to mainnet)

  • [ ] Ensure all contracts have been audited
  • [ ] Review audit reports for any critical or high-severity issues
  • [ ] Test deployment on a testnet first
  • [ ] Announce deployment to community (if applicable)
  • [ ] Monitor contracts for the first 24-48 hours after deployment
  • [ ] Have an incident response plan ready

Notes

Record any issues, deviations from the standard process, or important observations:

______________________________________________________________________________
______________________________________________________________________________
______________________________________________________________________________
______________________________________________________________________________
______________________________________________________________________________

Sign-Off

  • Deployed by: ________________
  • Date: ________________
  • Network: ________________
  • Block number at deployment start: ________________
  • Gas used (total): ________________
  • Total cost: ________________
Deployment Order

Deployment Order Quick Reference

This document provides a quick reference for the deployment order of sudoAMM v2 contracts.

Dependency Graph

┌─────────────────────────────────────────────────────────────────────┐
│                         EXTERNAL DEPENDENCY                          │
│                   Manifold Royalty Registry (pre-existing)           │
└───────────────────────────────┬─────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────────┐
│ STEP 1: RoyaltyEngine                                                │
└───────────────────────────────┬─────────────────────────────────────┘
                                │
                ┌───────────────┴───────────────┐
                ▼                               ▼
┌───────────────────────────┐   ┌───────────────────────────┐
│ STEP 2a:                  │   │ STEP 2b:                  │
│ LSSVMPairERC721ETH        │   │ LSSVMPairERC1155ETH       │
│ LSSVMPairERC721ERC20      │   │ LSSVMPairERC1155ERC20     │
└───────────┬───────────────┘   └───────────┬───────────────┘
            │                               │
            └───────────────┬───────────────┘
                            ▼
┌─────────────────────────────────────────────────────────────────────┐
│ STEP 3: LSSVMPairFactory                                             │
└───────────────┬─────────────────────────────────────┬───────────────┘
                │                                     │
                ▼                                     ▼
┌───────────────────────────┐           ┌───────────────────────────┐
│ STEP 4: Bonding Curves    │           │ STEP 5: VeryFastRouter    │
│ (independent)             │           │                           │
│ - LinearCurve             │           └───────────────────────────┘
│ - ExponentialCurve        │
│ - XykCurve                │
│ - GDACurve                │
└───────────────────────────┘
                
┌───────────────────────────┐
│ STEP 6: Property Checkers │
│ (independent)             │
│ - MerklePropertyChecker   │
│ - RangePropertyChecker    │
│ - PropertyCheckerFactory  │
└───────────────────────────┘

┌───────────────────────────────────────────────────────────────────┐
│ STEP 7: Settings                                                  │
│ - Splitter (independent)                                          │
│ - StandardSettings (requires Splitter + Factory)                 │
│ - StandardSettingsFactory (requires StandardSettings)            │
└───────────────────────────────────────────────────────────────────┘

Deployment Sequence

Phase 1: Foundation (Required)

  1. RoyaltyEngine ← Requires: Manifold Royalty Registry address

Phase 2: Templates (Required)

  1. LSSVMPairERC721ETH ← Requires: RoyaltyEngine
  2. LSSVMPairERC721ERC20 ← Requires: RoyaltyEngine
  3. LSSVMPairERC1155ETH ← Requires: RoyaltyEngine
  4. LSSVMPairERC1155ERC20 ← Requires: RoyaltyEngine

Phase 3: Factory (Required)

  1. LSSVMPairFactory ← Requires: All 4 templates from Phase 2

Phase 4: Extensions (Optional but Recommended)

4a. Bonding Curves (Independent)

  1. LinearCurve
  2. ExponentialCurve
  3. XykCurve
  4. GDACurve

4b. Router

  1. VeryFastRouter ← Requires: LSSVMPairFactory

4c. Property Checkers (Independent)

  1. MerklePropertyChecker (implementation)
  2. RangePropertyChecker (implementation)
  3. PropertyCheckerFactory ← Requires: Property checker implementations

4d. Settings

  1. Splitter (implementation)
  2. StandardSettings ← Requires: Splitter + LSSVMPairFactory
  3. StandardSettingsFactory ← Requires: StandardSettings

Post-Deployment Configuration

After all contracts are deployed, the factory owner must:

  1. Whitelist Bonding Curves (for each curve):

    factory.setBondingCurveAllowed(curveAddress, true)
    
  2. Whitelist Router:

    factory.setRouterAllowed(routerAddress, true)
    

Scripts Reference

| Order | Script | Contracts Deployed | |-------|--------|-------------------| | 1 | 01_DeployCore.s.sol | RoyaltyEngine, Templates, Factory | | 2 | 02_DeployBondingCurves.s.sol | All 4 bonding curves | | 3 | 03_DeployRouter.s.sol | VeryFastRouter | | 4 | 04_DeployPropertyCheckers.s.sol | Property checkers + factory | | 5 | 05_DeploySettings.s.sol | Settings system | | - | DeployAll.s.sol | Everything in order |

Minimal Deployment

For a minimal functional deployment, you only need:

  • Phase 1: RoyaltyEngine
  • Phase 2: All 4 templates
  • Phase 3: LSSVMPairFactory
  • Phase 4a: At least one bonding curve (e.g., LinearCurve)

This allows users to create pools, but they won't have access to:

  • Router functionality (manual interactions only)
  • Property checking
  • Settings system

Constructor Arguments Quick Reference

| Contract | Constructor Arguments | |----------|----------------------| | RoyaltyEngine | address royaltyRegistry | | LSSVMPairERC721ETH | IRoyaltyEngineV1 royaltyEngine | | LSSVMPairERC721ERC20 | IRoyaltyEngineV1 royaltyEngine | | LSSVMPairERC1155ETH | IRoyaltyEngineV1 royaltyEngine | | LSSVMPairERC1155ERC20 | IRoyaltyEngineV1 royaltyEngine | | LSSVMPairFactory | All 4 templates, feeRecipient, feeMultiplier, owner | | LinearCurve | None | | ExponentialCurve | None | | XykCurve | None | | GDACurve | None | | VeryFastRouter | ILSSVMPairFactoryLike factory | | MerklePropertyChecker | None (implementation) | | RangePropertyChecker | None (implementation) | | PropertyCheckerFactory | Both checker implementations | | Splitter | None (implementation) | | StandardSettings | Splitter impl, ILSSVMPairFactoryLike factory | | StandardSettingsFactory | StandardSettings impl |

Common Pitfalls

  1. Deploying out of order: Templates must be deployed before factory
  2. Forgetting to whitelist: Curves and router won't work until whitelisted
  3. Wrong royalty registry: Each network has a different address
  4. Fee too high: protocolFeeMultiplier must be ≤ 0.1e18 (10%)
  5. Wrong factory owner: Ensure FACTORY_OWNER is set correctly for post-deployment config

Deployment Features

  • ✅ Automatic factory configuration
  • ✅ Mnemonic support for key management
  • ✅ Chain ID validation
  • ✅ Comprehensive error handling
  • ✅ Helper scripts for common scenarios
  • ✅ Test NFT contracts for testing pools