├── .prettierignore ├── frontend ├── next.config.js ├── pages │ ├── _app.tsx │ └── index.tsx ├── package.json ├── src │ ├── styles │ │ └── globals.css │ ├── types │ │ └── index.ts │ ├── components │ │ ├── Layout.tsx │ │ └── ProjectList.tsx │ ├── hooks │ │ └── useProjects.ts │ └── utils │ │ └── api.ts └── tsconfig.json ├── .prettierrc ├── backend ├── src │ ├── routes │ │ ├── index.ts │ │ └── projectRoutes.ts │ ├── middleware │ │ ├── notFound.ts │ │ └── errorHandler.ts │ ├── types │ │ └── index.ts │ ├── config │ │ └── index.ts │ ├── index.ts │ ├── services │ │ └── projectService.ts │ └── controllers │ │ └── projectController.ts ├── tsconfig.json └── package.json ├── tsconfig.json ├── contracts └── core │ ├── Token.sol │ ├── TokenFactory.sol │ ├── LiquidityMigrator.sol │ └── BondingCurve.sol ├── .gitignore ├── .eslintrc.json ├── package.json ├── hardhat.config.ts ├── scripts └── deploy.ts ├── LICENSE ├── CONTRIBUTING.md ├── docs ├── DEPLOYMENT.md └── ARCHITECTURE.md └── README.md /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .next 3 | dist 4 | coverage 5 | cache 6 | artifacts 7 | *.log 8 | .env 9 | .env.* 10 | 11 | -------------------------------------------------------------------------------- /frontend/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | module.exports = nextConfig; 4 | 5 | 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "es5", 4 | "singleQuote": true, 5 | "printWidth": 100, 6 | "tabWidth": 2, 7 | "useTabs": false, 8 | "arrowParens": "avoid", 9 | "endOfLine": "lf" 10 | } 11 | 12 | -------------------------------------------------------------------------------- /backend/src/routes/index.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'express'; 2 | import projectRoutes from './projectRoutes'; 3 | 4 | const router = Router(); 5 | 6 | router.use('/projects', projectRoutes); 7 | 8 | export default router; 9 | 10 | -------------------------------------------------------------------------------- /frontend/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { AppProps } from 'next/app'; 3 | import '../src/styles/globals.css'; 4 | 5 | export default function App({ Component, pageProps }: AppProps) { 6 | return ; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /backend/src/middleware/notFound.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from 'express'; 2 | 3 | export const notFound = (req: Request, res: Response) => { 4 | res.status(404).json({ 5 | error: { 6 | message: `Route ${req.originalUrl} not found`, 7 | }, 8 | }); 9 | }; 10 | 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "moduleResolution": "node", 7 | "resolveJsonModule": true, 8 | "strict": true 9 | }, 10 | "include": ["hardhat.config.ts", "scripts", "test", "typechain-types"] 11 | } 12 | 13 | 14 | -------------------------------------------------------------------------------- /backend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "outDir": "dist", 7 | "strict": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "skipLibCheck": true 11 | }, 12 | "include": ["src/**/*"] 13 | } 14 | 15 | 16 | -------------------------------------------------------------------------------- /backend/src/routes/projectRoutes.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'express'; 2 | import { ProjectController } from '../controllers/projectController'; 3 | 4 | const router = Router(); 5 | 6 | router.post('/launch', ProjectController.createProject); 7 | router.get('/', ProjectController.getProjects); 8 | router.get('/:id', ProjectController.getProject); 9 | 10 | export default router; 11 | 12 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bsc-launchpad-frontend", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start" 9 | }, 10 | "dependencies": { 11 | "next": "14.2.4", 12 | "react": "18.2.0", 13 | "react-dom": "18.2.0" 14 | }, 15 | "devDependencies": { 16 | "typescript": "^5.4.0", 17 | "@types/react": "^18.2.0", 18 | "@types/node": "^20.11.30" 19 | } 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /frontend/src/styles/globals.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | body { 8 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 9 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 10 | sans-serif; 11 | -webkit-font-smoothing: antialiased; 12 | -moz-osx-font-smoothing: grayscale; 13 | } 14 | 15 | code { 16 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 17 | monospace; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /backend/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export interface Project { 2 | id: string; 3 | name: string; 4 | symbol: string; 5 | tokenAddress?: string; 6 | creator: string; 7 | createdAt: Date; 8 | status: 'pending' | 'active' | 'completed' | 'failed'; 9 | } 10 | 11 | export interface LaunchRequest { 12 | name: string; 13 | symbol: string; 14 | decimals?: number; 15 | totalSupply?: string; 16 | } 17 | 18 | export interface ApiResponse { 19 | success: boolean; 20 | data?: T; 21 | error?: string; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /frontend/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export interface Project { 2 | id: string; 3 | name: string; 4 | symbol: string; 5 | tokenAddress?: string; 6 | creator: string; 7 | createdAt: string; 8 | status: 'pending' | 'active' | 'completed' | 'failed'; 9 | } 10 | 11 | export interface LaunchRequest { 12 | name: string; 13 | symbol: string; 14 | decimals?: number; 15 | totalSupply?: string; 16 | } 17 | 18 | export interface ApiResponse { 19 | success: boolean; 20 | data?: T; 21 | error?: string; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /contracts/core/Token.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.24; 3 | 4 | import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; 6 | 7 | contract Token is ERC20, Ownable { 8 | constructor( 9 | string memory name_, 10 | string memory symbol_, 11 | uint256 totalSupply_, 12 | address owner_ 13 | ) ERC20(name_, symbol_) Ownable(owner_) { 14 | _mint(owner_, totalSupply_); 15 | } 16 | } 17 | 18 | 19 | -------------------------------------------------------------------------------- /backend/src/config/index.ts: -------------------------------------------------------------------------------- 1 | import dotenv from 'dotenv'; 2 | 3 | dotenv.config(); 4 | 5 | export const config = { 6 | port: parseInt(process.env.PORT || '4100', 10), 7 | nodeEnv: process.env.NODE_ENV || 'development', 8 | cors: { 9 | origin: process.env.CORS_ORIGIN || '*', 10 | }, 11 | blockchain: { 12 | bscTestnetUrl: process.env.BSC_TESTNET_URL || 'https://bsc-testnet.publicnode.com', 13 | bscUrl: process.env.BSC_URL || 'https://bsc-dataseed.binance.org', 14 | privateKey: process.env.PRIVATE_KEY || '', 15 | }, 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bsc-launchpad-backend", 3 | "version": "0.1.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "ts-node-dev --respawn src/index.ts", 8 | "build": "tsc -p .", 9 | "start": "node dist/index.js" 10 | }, 11 | "dependencies": { 12 | "cors": "^2.8.5", 13 | "express": "^4.19.2", 14 | "morgan": "^1.10.0" 15 | }, 16 | "devDependencies": { 17 | "@types/cors": "^2.8.17", 18 | "@types/express": "^4.17.21", 19 | "@types/node": "^20.11.30", 20 | "ts-node": "^10.9.2", 21 | "ts-node-dev": "^2.0.0", 22 | "typescript": "^5.4.0" 23 | } 24 | } 25 | 26 | 27 | -------------------------------------------------------------------------------- /frontend/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Layout } from '../src/components/Layout'; 3 | import { ProjectList } from '../src/components/ProjectList'; 4 | 5 | export default function Home() { 6 | return ( 7 | 8 | 9 | Welcome to BSC Memecoin Launchpad 10 | Token factory + bonding curve sale + auto-liquidity migration to PancakeSwap. 11 | 12 | Create token 13 | Buy via bonding curve 14 | Auto-migrate to LP 15 | 16 | 17 | 18 | 19 | ); 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /contracts/core/TokenFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.24; 3 | 4 | import {Token} from "./Token.sol"; 5 | 6 | contract TokenFactory { 7 | event TokenCreated(address indexed token, address indexed creator); 8 | 9 | function createToken( 10 | string calldata name_, 11 | string calldata symbol_, 12 | uint8 decimals_, 13 | uint256 totalSupply_ 14 | ) external returns (address token) { 15 | Token t = new Token(name_, symbol_, totalSupply_ * (10 ** uint256(decimals_)), msg.sender); 16 | token = address(t); 17 | emit TokenCreated(token, msg.sender); 18 | } 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /backend/src/middleware/errorHandler.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response, NextFunction } from 'express'; 2 | 3 | export interface AppError extends Error { 4 | statusCode?: number; 5 | } 6 | 7 | export const errorHandler = ( 8 | err: AppError, 9 | req: Request, 10 | res: Response, 11 | next: NextFunction 12 | ) => { 13 | const statusCode = err.statusCode || 500; 14 | const message = err.message || 'Internal Server Error'; 15 | 16 | console.error(`Error [${statusCode}]:`, message); 17 | 18 | res.status(statusCode).json({ 19 | error: { 20 | message, 21 | ...(process.env.NODE_ENV === 'development' && { stack: err.stack }), 22 | }, 23 | }); 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": false, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "bundler", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "baseUrl": ".", 17 | "paths": { 18 | "@/*": ["./src/*"] 19 | } 20 | }, 21 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "src/**/*"], 22 | "exclude": ["node_modules"] 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | .pnp 4 | .pnp.js 5 | 6 | # Testing 7 | coverage/ 8 | *.lcov 9 | 10 | # Production builds 11 | dist/ 12 | build/ 13 | .next/ 14 | out/ 15 | 16 | # Environment variables 17 | .env 18 | .env.local 19 | .env.development.local 20 | .env.test.local 21 | .env.production.local 22 | .env.* 23 | 24 | # Logs 25 | npm-debug.log* 26 | yarn-debug.log* 27 | yarn-error.log* 28 | lerna-debug.log* 29 | *.log 30 | 31 | # Hardhat 32 | cache/ 33 | artifacts/ 34 | typechain-types/ 35 | 36 | # IDE 37 | .vscode/ 38 | .idea/ 39 | *.swp 40 | *.swo 41 | *~ 42 | 43 | # OS 44 | .DS_Store 45 | Thumbs.db 46 | desktop.ini 47 | 48 | # Temporary files 49 | *.tmp 50 | *.temp 51 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "parserOptions": { 5 | "ecmaVersion": 2020, 6 | "sourceType": "module", 7 | "project": "./tsconfig.json" 8 | }, 9 | "plugins": ["@typescript-eslint"], 10 | "extends": [ 11 | "eslint:recommended", 12 | "plugin:@typescript-eslint/recommended" 13 | ], 14 | "rules": { 15 | "@typescript-eslint/no-explicit-any": "warn", 16 | "@typescript-eslint/explicit-module-boundary-types": "off", 17 | "no-console": "off" 18 | }, 19 | "ignorePatterns": [ 20 | "node_modules", 21 | "dist", 22 | ".next", 23 | "coverage", 24 | "cache", 25 | "artifacts" 26 | ] 27 | } 28 | 29 | -------------------------------------------------------------------------------- /frontend/src/components/Layout.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactNode } from 'react'; 2 | 3 | interface LayoutProps { 4 | children: ReactNode; 5 | } 6 | 7 | export const Layout: React.FC = ({ children }) => { 8 | return ( 9 | 10 | 11 | BSC Memecoin Launchpad 12 | 13 | {children} 14 | 17 | 18 | ); 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /frontend/src/components/ProjectList.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Project } from '../types'; 3 | import { useProjects } from '../hooks/useProjects'; 4 | 5 | export const ProjectList: React.FC = () => { 6 | const { projects, loading, error } = useProjects(); 7 | 8 | if (loading) return Loading projects...; 9 | if (error) return Error: {error}; 10 | if (projects.length === 0) return No projects found; 11 | 12 | return ( 13 | 14 | Projects 15 | 16 | {projects.map((project) => ( 17 | 18 | {project.name} ({project.symbol}) - {project.status} 19 | 20 | ))} 21 | 22 | 23 | ); 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bsc-memecoin-launchpad", 3 | "version": "0.1.0", 4 | "private": true, 5 | "description": "Pump.fun-style launchpad for Binance Smart Chain", 6 | "scripts": { 7 | "build": "hardhat compile", 8 | "test": "hardhat test", 9 | "lint": "eslint . --ext .ts,.tsx", 10 | "format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"", 11 | "format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md}\"" 12 | }, 13 | "devDependencies": { 14 | "@nomicfoundation/hardhat-toolbox": "^4.0.0", 15 | "@types/node": "^20.11.30", 16 | "@typescript-eslint/eslint-plugin": "^7.0.0", 17 | "@typescript-eslint/parser": "^7.0.0", 18 | "eslint": "^8.57.0", 19 | "hardhat": "^2.22.10", 20 | "prettier": "^3.2.5", 21 | "typescript": "^5.4.0" 22 | }, 23 | "dependencies": { 24 | "@openzeppelin/contracts": "^5.0.2", 25 | "dotenv": "^16.4.5" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /frontend/src/hooks/useProjects.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react'; 2 | import { Project } from '../types'; 3 | import { apiClient } from '../utils/api'; 4 | 5 | export const useProjects = () => { 6 | const [projects, setProjects] = useState([]); 7 | const [loading, setLoading] = useState(true); 8 | const [error, setError] = useState(null); 9 | 10 | useEffect(() => { 11 | const fetchProjects = async () => { 12 | try { 13 | setLoading(true); 14 | const response = await apiClient.get('/projects'); 15 | if (response.success && response.data) { 16 | setProjects(response.data); 17 | } 18 | } catch (err) { 19 | setError(err instanceof Error ? err.message : 'Failed to fetch projects'); 20 | } finally { 21 | setLoading(false); 22 | } 23 | }; 24 | 25 | fetchProjects(); 26 | }, []); 27 | 28 | return { projects, loading, error }; 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import { HardhatUserConfig } from "hardhat/config"; 2 | import "@nomicfoundation/hardhat-toolbox"; 3 | import dotenv from "dotenv"; 4 | 5 | dotenv.config(); 6 | 7 | const config: HardhatUserConfig = { 8 | solidity: { 9 | version: "0.8.24", 10 | settings: { 11 | optimizer: { 12 | enabled: true, 13 | runs: 200, 14 | }, 15 | }, 16 | }, 17 | paths: { 18 | sources: "./contracts", 19 | tests: "./test", 20 | cache: "./cache", 21 | artifacts: "./artifacts", 22 | }, 23 | networks: { 24 | hardhat: {}, 25 | bscTestnet: { 26 | url: process.env.BSC_TESTNET_URL || "https://bsc-testnet.publicnode.com", 27 | accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [], 28 | }, 29 | bsc: { 30 | url: process.env.BSC_URL || "https://bsc-dataseed.binance.org", 31 | accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [], 32 | }, 33 | }, 34 | }; 35 | 36 | export default config; 37 | -------------------------------------------------------------------------------- /backend/src/index.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import cors from 'cors'; 3 | import morgan from 'morgan'; 4 | import { config } from './config'; 5 | import routes from './routes'; 6 | import { errorHandler } from './middleware/errorHandler'; 7 | import { notFound } from './middleware/notFound'; 8 | 9 | const app = express(); 10 | 11 | // Middleware 12 | app.use(cors({ origin: config.cors.origin })); 13 | app.use(express.json()); 14 | app.use(express.urlencoded({ extended: true })); 15 | app.use(morgan(config.nodeEnv === 'production' ? 'combined' : 'dev')); 16 | 17 | // Health check 18 | app.get('/health', (_req, res) => { 19 | res.json({ status: 'ok', timestamp: new Date().toISOString() }); 20 | }); 21 | 22 | // API Routes 23 | app.use('/api', routes); 24 | 25 | // 404 handler 26 | app.use(notFound); 27 | 28 | // Error handler 29 | app.use(errorHandler); 30 | 31 | const port = config.port; 32 | app.listen(port, () => { 33 | console.log(`🚀 Backend server listening on port ${port}`); 34 | console.log(`📝 Environment: ${config.nodeEnv}`); 35 | }); 36 | -------------------------------------------------------------------------------- /contracts/core/LiquidityMigrator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.24; 3 | 4 | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; 6 | 7 | /// @notice Placeholder migrator. Integrate PancakeSwap Router to add liquidity and optionally burn LP. 8 | contract LiquidityMigrator is Ownable { 9 | address public router; // PancakeSwap v2 router address 10 | address public lpRecipient; // set to burn address if burning 11 | 12 | constructor(address owner_, address router_, address lpRecipient_) Ownable(owner_) { 13 | router = router_; 14 | lpRecipient = lpRecipient_; 15 | } 16 | 17 | function setRouter(address router_) external onlyOwner { 18 | router = router_; 19 | } 20 | 21 | function setLpRecipient(address lpRecipient_) external onlyOwner { 22 | lpRecipient = lpRecipient_; 23 | } 24 | 25 | // addLiquidityETH(token, tokenAmount, minToken, minETH, to, deadline) 26 | // will be wired once router is configured 27 | } 28 | 29 | 30 | -------------------------------------------------------------------------------- /scripts/deploy.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | 3 | async function main() { 4 | const [deployer] = await ethers.getSigners(); 5 | console.log("Deployer:", deployer.address); 6 | console.log("Balance:", ethers.formatEther(await ethers.provider.getBalance(deployer.address)), "BNB"); 7 | 8 | // Deploy TokenFactory 9 | const TokenFactory = await ethers.getContractFactory("TokenFactory"); 10 | const factory = await TokenFactory.deploy(); 11 | await factory.waitForDeployment(); 12 | const factoryAddress = await factory.getAddress(); 13 | console.log("TokenFactory deployed to:", factoryAddress); 14 | 15 | // Example: create a token (name, symbol, decimals, supply) 16 | console.log("\nCreating example token..."); 17 | const tx = await factory.createToken("Meme", "MEME", 18, ethers.parseUnits("1000000000", 0)); 18 | const rc = await tx.wait(); 19 | const ev = rc?.logs?.[0] as any; 20 | console.log("Token created at:", ev?.address || "-"); 21 | } 22 | 23 | main() 24 | .then(() => process.exit(0)) 25 | .catch((error) => { 26 | console.error(error); 27 | process.exit(1); 28 | }); 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 BSC Memecoin Launchpad 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /backend/src/services/projectService.ts: -------------------------------------------------------------------------------- 1 | import { Project } from '../types'; 2 | 3 | // In-memory store - replace with database in production 4 | const projects: Map = new Map(); 5 | 6 | export class ProjectService { 7 | static createProject(data: { 8 | name: string; 9 | symbol: string; 10 | creator: string; 11 | }): Project { 12 | const id = `project_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; 13 | const project: Project = { 14 | id, 15 | name: data.name, 16 | symbol: data.symbol, 17 | creator: data.creator, 18 | createdAt: new Date(), 19 | status: 'pending', 20 | }; 21 | 22 | projects.set(id, project); 23 | return project; 24 | } 25 | 26 | static getProject(id: string): Project | undefined { 27 | return projects.get(id); 28 | } 29 | 30 | static getAllProjects(): Project[] { 31 | return Array.from(projects.values()); 32 | } 33 | 34 | static updateProject(id: string, updates: Partial): Project | null { 35 | const project = projects.get(id); 36 | if (!project) return null; 37 | 38 | const updated = { ...project, ...updates }; 39 | projects.set(id, updated); 40 | return updated; 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guide 2 | 3 | Thank you for considering contributing to the BSC Memecoin Launchpad project! 4 | 5 | ## Development Setup 6 | 7 | 1. Fork the repository 8 | 2. Clone your fork: `git clone https://github.com/your-username/bsc-memecoin-launchpad.git` 9 | 3. Install dependencies: `pnpm install` 10 | 4. Create a new branch: `git checkout -b feature/your-feature-name` 11 | 12 | ## Code Style 13 | 14 | - Follow the existing code style 15 | - Use TypeScript for all new code 16 | - Run `pnpm format` before committing 17 | - Run `pnpm lint` to check for linting errors 18 | 19 | ## Commit Messages 20 | 21 | Use clear, descriptive commit messages: 22 | - `feat: add wallet connection` 23 | - `fix: resolve bonding curve calculation` 24 | - `docs: update deployment guide` 25 | - `refactor: reorganize contract structure` 26 | 27 | ## Pull Request Process 28 | 29 | 1. Ensure your code passes all tests 30 | 2. Update documentation if needed 31 | 3. Create a pull request with a clear description 32 | 4. Wait for code review and address any feedback 33 | 34 | ## Testing 35 | 36 | - Write tests for new features 37 | - Ensure all existing tests pass 38 | - Test on BSC testnet before mainnet deployment 39 | 40 | ## Security 41 | 42 | - Never commit private keys or sensitive data 43 | - Report security vulnerabilities privately 44 | - Follow security best practices for smart contracts 45 | 46 | -------------------------------------------------------------------------------- /docs/DEPLOYMENT.md: -------------------------------------------------------------------------------- 1 | # Deployment Guide 2 | 3 | ## Prerequisites 4 | 5 | - Node.js 18+ 6 | - pnpm/npm/yarn 7 | - Hardhat 8 | - BSC wallet with BNB for gas 9 | 10 | ## Environment Setup 11 | 12 | 1. Copy `.env.example` to `.env` 13 | 2. Fill in required environment variables: 14 | - `PRIVATE_KEY`: Your wallet private key (for deployment) 15 | - `BSC_TESTNET_URL` or `BSC_URL`: RPC endpoint 16 | - `NEXT_PUBLIC_API_URL`: Backend API URL (for frontend) 17 | 18 | ## Build 19 | 20 | ```bash 21 | # Install dependencies 22 | pnpm install 23 | 24 | # Build contracts 25 | pnpm build 26 | 27 | # Build backend 28 | cd backend && pnpm build 29 | 30 | # Build frontend 31 | cd frontend && pnpm build 32 | ``` 33 | 34 | ## Deploy Contracts 35 | 36 | ```bash 37 | # Deploy to BSC Testnet 38 | pnpm hardhat run scripts/deploy.ts --network bscTestnet 39 | 40 | # Deploy to BSC Mainnet 41 | pnpm hardhat run scripts/deploy.ts --network bsc 42 | ``` 43 | 44 | ## Run Services 45 | 46 | ### Backend 47 | ```bash 48 | cd backend 49 | pnpm dev # Development mode 50 | pnpm start # Production mode 51 | ``` 52 | 53 | ### Frontend 54 | ```bash 55 | cd frontend 56 | pnpm dev # Development mode 57 | pnpm start # Production mode 58 | ``` 59 | 60 | ## Testing 61 | 62 | ```bash 63 | # Run contract tests 64 | pnpm test 65 | 66 | # Run backend tests (when implemented) 67 | cd backend && pnpm test 68 | 69 | # Run frontend tests (when implemented) 70 | cd frontend && pnpm test 71 | ``` 72 | 73 | -------------------------------------------------------------------------------- /frontend/src/utils/api.ts: -------------------------------------------------------------------------------- 1 | import { ApiResponse } from '../types'; 2 | 3 | const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4100/api'; 4 | 5 | export class ApiClient { 6 | private baseUrl: string; 7 | 8 | constructor(baseUrl: string = API_BASE_URL) { 9 | this.baseUrl = baseUrl; 10 | } 11 | 12 | private async request( 13 | endpoint: string, 14 | options: RequestInit = {} 15 | ): Promise> { 16 | const url = `${this.baseUrl}${endpoint}`; 17 | 18 | const response = await fetch(url, { 19 | ...options, 20 | headers: { 21 | 'Content-Type': 'application/json', 22 | ...options.headers, 23 | }, 24 | }); 25 | 26 | if (!response.ok) { 27 | const error = await response.json().catch(() => ({ error: 'Unknown error' })); 28 | throw new Error(error.error?.message || 'Request failed'); 29 | } 30 | 31 | return response.json(); 32 | } 33 | 34 | async get(endpoint: string): Promise> { 35 | return this.request(endpoint, { method: 'GET' }); 36 | } 37 | 38 | async post(endpoint: string, data?: any): Promise> { 39 | return this.request(endpoint, { 40 | method: 'POST', 41 | body: JSON.stringify(data), 42 | }); 43 | } 44 | 45 | async put(endpoint: string, data?: any): Promise> { 46 | return this.request(endpoint, { 47 | method: 'PUT', 48 | body: JSON.stringify(data), 49 | }); 50 | } 51 | 52 | async delete(endpoint: string): Promise> { 53 | return this.request(endpoint, { method: 'DELETE' }); 54 | } 55 | } 56 | 57 | export const apiClient = new ApiClient(); 58 | 59 | -------------------------------------------------------------------------------- /docs/ARCHITECTURE.md: -------------------------------------------------------------------------------- 1 | # Architecture Overview 2 | 3 | ## Project Structure 4 | 5 | This is a monorepo containing three main components: 6 | 7 | ### 1. Smart Contracts (`contracts/`) 8 | - **core/**: Main contract implementations 9 | - `Token.sol`: ERC20 token implementation 10 | - `TokenFactory.sol`: Factory for creating tokens 11 | - `BondingCurve.sol`: Linear bonding curve for token sales 12 | - `LiquidityMigrator.sol`: Handles liquidity migration to PancakeSwap 13 | - **interfaces/**: Contract interfaces (to be added) 14 | - **libraries/**: Shared libraries (to be added) 15 | 16 | ### 2. Backend (`backend/`) 17 | - **src/config/**: Configuration management 18 | - **src/controllers/**: Request handlers 19 | - **src/services/**: Business logic 20 | - **src/routes/**: API route definitions 21 | - **src/middleware/**: Express middleware (error handling, etc.) 22 | - **src/types/**: TypeScript type definitions 23 | 24 | ### 3. Frontend (`frontend/`) 25 | - **src/components/**: React components 26 | - **src/hooks/**: Custom React hooks 27 | - **src/utils/**: Utility functions 28 | - **src/types/**: TypeScript type definitions 29 | - **src/styles/**: Styling files 30 | - **pages/**: Next.js pages 31 | 32 | ## Technology Stack 33 | 34 | - **Blockchain**: Binance Smart Chain (BSC) 35 | - **Smart Contracts**: Solidity 0.8.24 + OpenZeppelin 36 | - **Development**: Hardhat 37 | - **Backend**: Node.js + Express + TypeScript 38 | - **Frontend**: Next.js + React + TypeScript 39 | 40 | ## Data Flow 41 | 42 | 1. User creates a token via frontend 43 | 2. Frontend calls backend API 44 | 3. Backend interacts with smart contracts 45 | 4. Token is deployed on BSC 46 | 5. Users can buy tokens via bonding curve 47 | 6. When threshold is reached, liquidity migrates to PancakeSwap 48 | 49 | -------------------------------------------------------------------------------- /backend/src/controllers/projectController.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response, NextFunction } from 'express'; 2 | import { ProjectService } from '../services/projectService'; 3 | import { LaunchRequest } from '../types'; 4 | import { AppError } from '../middleware/errorHandler'; 5 | 6 | export class ProjectController { 7 | static async createProject(req: Request, res: Response, next: NextFunction) { 8 | try { 9 | const { name, symbol } = req.body as LaunchRequest; 10 | 11 | if (!name || !symbol) { 12 | const error: AppError = new Error('name and symbol are required'); 13 | error.statusCode = 400; 14 | throw error; 15 | } 16 | 17 | const project = ProjectService.createProject({ 18 | name, 19 | symbol, 20 | creator: req.ip || 'unknown', 21 | }); 22 | 23 | res.status(201).json({ 24 | success: true, 25 | data: project, 26 | }); 27 | } catch (error) { 28 | next(error); 29 | } 30 | } 31 | 32 | static async getProjects(req: Request, res: Response, next: NextFunction) { 33 | try { 34 | const projects = ProjectService.getAllProjects(); 35 | res.json({ 36 | success: true, 37 | data: projects, 38 | }); 39 | } catch (error) { 40 | next(error); 41 | } 42 | } 43 | 44 | static async getProject(req: Request, res: Response, next: NextFunction) { 45 | try { 46 | const { id } = req.params; 47 | const project = ProjectService.getProject(id); 48 | 49 | if (!project) { 50 | const error: AppError = new Error('Project not found'); 51 | error.statusCode = 404; 52 | throw error; 53 | } 54 | 55 | res.json({ 56 | success: true, 57 | data: project, 58 | }); 59 | } catch (error) { 60 | next(error); 61 | } 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /contracts/core/BondingCurve.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.24; 3 | 4 | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; 6 | 7 | /// @notice Minimal linear bonding curve: price grows with sold amount 8 | contract BondingCurve is Ownable { 9 | IERC20 public immutable token; 10 | address public immutable treasury; 11 | 12 | uint256 public sold; // tokens sold (base units) 13 | uint256 public basePrice; // wei per token base 14 | uint256 public slope; // wei per token increment per token sold 15 | uint256 public feeBps; // fee to treasury on purchases (in basis points) 16 | 17 | event Bought(address indexed buyer, uint256 amount, uint256 paid); 18 | 19 | constructor( 20 | address token_, 21 | address treasury_, 22 | uint256 basePrice_, 23 | uint256 slope_, 24 | uint256 feeBps_ 25 | ) Ownable(msg.sender) { 26 | token = IERC20(token_); 27 | treasury = treasury_; 28 | basePrice = basePrice_; 29 | slope = slope_; 30 | feeBps = feeBps_; 31 | } 32 | 33 | function priceToBuy(uint256 amount) public view returns (uint256) { 34 | // Integral of linear price: sum(base + slope*(sold+i)) for i in [1..amount] 35 | // = amount*base + slope*(amount*sold + amount*(amount+1)/2) 36 | uint256 a = amount; 37 | uint256 s = sold; 38 | uint256 linear = a * basePrice; 39 | uint256 slopePart = slope * (a * s + (a * (a + 1)) / 2); 40 | return linear + slopePart; 41 | } 42 | 43 | function buy(uint256 amount, uint256 minTokensOut) external payable { 44 | require(amount > 0, "amount=0"); 45 | uint256 cost = priceToBuy(amount); 46 | require(msg.value >= cost, "insufficient BNB"); 47 | 48 | uint256 fee = (cost * feeBps) / 10_000; 49 | (bool okFee, ) = payable(treasury).call{value: fee}(""); 50 | require(okFee, "fee transfer failed"); 51 | 52 | // remaining stays in contract to later seed LP via migrator 53 | sold += amount; 54 | require(token.transfer(msg.sender, amount), "token transfer failed"); 55 | require(amount >= minTokensOut, "slippage"); 56 | 57 | emit Bought(msg.sender, amount, cost); 58 | 59 | // refund any excess 60 | if (msg.value > cost) { 61 | (bool okRefund, ) = payable(msg.sender).call{value: msg.value - cost}(""); 62 | require(okRefund, "refund failed"); 63 | } 64 | } 65 | } 66 | 67 | 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BSC Memecoin Launchpad 2 | 3 | Pump.fun-style launchpad for Binance Smart Chain: token factory + bonding curve sale + auto-liquidity migration to PancakeSwap. Includes Solidity contracts, a Hardhat toolchain, a TypeScript backend, and a minimal Next.js frontend. 4 | 5 | ## Contact Me 6 | 7 | - Telegram: `@blategold` 8 | 9 | ## Highlights 10 | 11 | - Token factory issues ERC20 tokens with fixed total supply 12 | - Bonding curve sale (linear baseline) with platform fee to treasury 13 | - Auto-liquidity migration hook for PancakeSwap and optional LP burn 14 | - Backend API stubs for project creation and sale state 15 | - Minimal Next.js UI scaffold 16 | 17 | ## Tech Stack 18 | 19 | - Chain: BSC (EVM) 20 | - Contracts: Solidity + OpenZeppelin 21 | - Tooling: Hardhat + TypeScript 22 | - Backend: Node.js + TypeScript (Express) 23 | - Frontend: Next.js + React + TypeScript 24 | 25 | --- 26 | 27 | ## Project Structure 28 | 29 | ``` 30 | bsc-memecoin-launchpad/ 31 | ├── contracts/ # Smart contracts 32 | │ ├── core/ # Core contract implementations 33 | │ │ ├── Token.sol 34 | │ │ ├── TokenFactory.sol 35 | │ │ ├── BondingCurve.sol 36 | │ │ └── LiquidityMigrator.sol 37 | │ ├── interfaces/ # Contract interfaces 38 | │ └── libraries/ # Shared libraries 39 | ├── scripts/ # Deployment scripts 40 | │ └── deploy.ts 41 | ├── test/ # Test files 42 | │ ├── unit/ # Unit tests 43 | │ └── integration/ # Integration tests 44 | ├── backend/ # Backend API 45 | │ └── src/ 46 | │ ├── config/ # Configuration 47 | │ ├── controllers/ # Request handlers 48 | │ ├── services/ # Business logic 49 | │ ├── routes/ # API routes 50 | │ ├── middleware/ # Express middleware 51 | │ ├── types/ # TypeScript types 52 | │ └── index.ts # Entry point 53 | ├── frontend/ # Frontend application 54 | │ ├── src/ 55 | │ │ ├── components/ # React components 56 | │ │ ├── hooks/ # Custom hooks 57 | │ │ ├── utils/ # Utility functions 58 | │ │ ├── types/ # TypeScript types 59 | │ │ └── styles/ # Styling files 60 | │ └── pages/ # Next.js pages 61 | ├── docs/ # Documentation 62 | │ ├── ARCHITECTURE.md 63 | │ └── DEPLOYMENT.md 64 | ├── hardhat.config.ts # Hardhat configuration 65 | ├── package.json # Root package.json 66 | ├── tsconfig.json # TypeScript configuration 67 | ├── .eslintrc.json # ESLint configuration 68 | ├── .prettierrc # Prettier configuration 69 | ├── .gitignore # Git ignore rules 70 | └── README.md # This file 71 | ``` 72 | 73 | --- 74 | 75 | ## Quickstart 76 | 77 | ### Prerequisites 78 | 79 | - Node.js 18+ 80 | - pnpm/npm/yarn 81 | - BSC wallet with BNB for gas (for deployment) 82 | 83 | ### Installation 84 | 85 | ```bash 86 | # Install root dependencies 87 | pnpm install 88 | 89 | # Install backend dependencies 90 | cd backend && pnpm install && cd .. 91 | 92 | # Install frontend dependencies 93 | cd frontend && pnpm install && cd .. 94 | ``` 95 | 96 | ### Environment Setup 97 | 98 | 1. Copy `.env.example` to `.env` (if available) 99 | 2. Configure environment variables: 100 | - `PRIVATE_KEY`: Your wallet private key (for contract deployment) 101 | - `BSC_TESTNET_URL` or `BSC_URL`: RPC endpoint 102 | - `PORT`: Backend server port (default: 4100) 103 | - `NEXT_PUBLIC_API_URL`: Backend API URL for frontend 104 | 105 | ### Build 106 | 107 | ```bash 108 | # Build contracts 109 | pnpm build 110 | 111 | # Build backend 112 | cd backend && pnpm build && cd .. 113 | 114 | # Build frontend 115 | cd frontend && pnpm build && cd .. 116 | ``` 117 | 118 | ### Development 119 | 120 | ```bash 121 | # Run backend (in one terminal) 122 | cd backend && pnpm dev 123 | 124 | # Run frontend (in another terminal) 125 | cd frontend && pnpm dev 126 | ``` 127 | 128 | ### Test 129 | 130 | ```bash 131 | # Run contract tests 132 | pnpm test 133 | ``` 134 | 135 | ### Deploy Contracts 136 | 137 | ```bash 138 | # Deploy to BSC Testnet 139 | pnpm hardhat run scripts/deploy.ts --network bscTestnet 140 | 141 | # Deploy to BSC Mainnet 142 | pnpm hardhat run scripts/deploy.ts --network bsc 143 | ``` 144 | 145 | --- 146 | 147 | ## Contracts Overview 148 | 149 | - TokenFactory: deploys ERC20 token and optionally allocates inventory to the bonding curve 150 | - BondingCurve: sells tokens for BNB on a simple linear curve with fee to treasury 151 | - LiquidityMigrator: placeholder hook to create LP on PancakeSwap and burn LP tokens 152 | 153 | Security notes: 154 | - Use audited OpenZeppelin libraries 155 | - Apply caps, cooldowns, and per-wallet limits if needed 156 | - Thoroughly test migration logic on testnet 157 | 158 | --- 159 | 160 | ## Documentation 161 | 162 | - [Architecture Overview](docs/ARCHITECTURE.md) - Detailed architecture documentation 163 | - [Deployment Guide](docs/DEPLOYMENT.md) - Step-by-step deployment instructions 164 | 165 | ## Development 166 | 167 | ### Code Quality 168 | 169 | The project uses ESLint and Prettier for code quality: 170 | 171 | ```bash 172 | # Format code 173 | pnpm prettier --write . 174 | 175 | # Lint code 176 | pnpm eslint . 177 | ``` 178 | 179 | ### Project Structure 180 | 181 | - **Contracts**: Organized in `contracts/core/` with interfaces and libraries separated 182 | - **Backend**: Follows MVC pattern with controllers, services, and routes 183 | - **Frontend**: Component-based architecture with custom hooks and utilities 184 | 185 | ## Roadmap 186 | 187 | - [ ] Implement PancakeSwap router integration and LP burn logic 188 | - [ ] Add creator fee/supply options and allowlists 189 | - [ ] Indexer and events for sale analytics 190 | - [ ] Frontend wallet connect and full flows 191 | - [ ] Comprehensive test coverage 192 | - [ ] CI/CD pipeline setup 193 | 194 | ## Security 195 | 196 | ⚠️ **Important Security Notes**: 197 | - Use audited OpenZeppelin libraries 198 | - Apply caps, cooldowns, and per-wallet limits if needed 199 | - Thoroughly test migration logic on testnet before mainnet deployment 200 | - Never commit private keys or sensitive data to version control 201 | - Conduct security audits before mainnet deployment 202 | 203 | ## License 204 | 205 | MIT (proposed) 206 | 207 | ## Contact 208 | 209 | - Telegram: `@blategold` 210 | 211 | --------------------------------------------------------------------------------
Token factory + bonding curve sale + auto-liquidity migration to PancakeSwap.