Skip to content

Josh9281/KASY_onchain

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GroupPay MVP

A production-grade Solidity smart contract system for group payments with atomic settlement, built with Foundry and OpenZeppelin.

Overview

GroupPay enables N-of-N group payments where all participants must contribute before funds are released to the merchant. Key features:

  • Atomic Settlement: All-or-nothing payment processing
  • Deadline-based: Automatic refund capability after deadline
  • Cashback Support: Optional cashback via global treasury
  • Factory Pattern: EIP-1167 minimal proxy clones for gas efficiency
  • Production Security: ReentrancyGuard, SafeERC20, comprehensive error handling

Architecture

GroupFactory (EIP-1167 Factory)
├── GroupEscrow (Implementation + Clones)
│   ├── State Machine: Pending → Settled/Refunding → Closed
│   ├── Participant Management (allowlist)
│   └── Atomic Settlement Logic
├── CashbackTreasury (Optional)
│   ├── Authorized Escrow Management
│   └── Equal Distribution Payouts
└── MockUSDC (Testing)
    └── 6-decimal USDC simulation

Key Invariants

No Partial Settlement: settle() only succeeds if paidCount == N and block.timestamp <= deadline
Single Deposit: Each participant deposits exactly perUser amount once
Refund Correctness: Participants can never withdraw more than deposited
Conservation: Σ deposits = merchantPayout + Σ refunds + Σ cashback
Safety: CEI pattern, nonReentrant, SafeERC20 transfers

Prerequisites

# Install Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup

# Install dependencies
forge install

🚀 Deployment Guide

Phase 1: Local Testing (Start Here!)

Perfect for development and testing. Uses fake USDC and pre-funded accounts.

# 1. Start local blockchain
anvil

# 2. Deploy contracts (new terminal)
forge script script/DeployLocal.s.sol --rpc-url http://localhost:8545 --broadcast

# 3. Run comprehensive tests
forge test --gas-report

# 4. Create test group
forge script script/CreateGroup.s.sol --rpc-url http://localhost:8545 --broadcast

✅ Local deployment gives you:

  • All contracts deployed instantly
  • 5 pre-funded test accounts (1,000 USDC each)
  • Treasury funded with 10,000 USDC
  • Real gas cost estimates
  • Complete working demo

Phase 2: Base Sepolia (Live Testnet)

Deploy to real blockchain for team demos and integration testing.

Step 1: Get Requirements

# 1. Get Base Sepolia ETH (free)
# Visit: https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet
# Need: ~0.01 ETH for deployment

# 2. Get BaseScan API key (free)
# Visit: https://basescan.org/apis
# Create account → Get API key

Step 2: Configure Environment

# Copy template
cp .env.example .env

# Edit .env file with YOUR details:
PRIVATE_KEY=0x1234567890abcdef...  # Your wallet private key (with 0x prefix!)
BASE_SEPOLIA_RPC=https://sepolia.base.org
BASESCAN_API_KEY=ABC123...         # Your BaseScan API key

Step 3: Deploy System

# Deploy all contracts to Base Sepolia
source .env && forge script script/DeployBaseSepolia.s.sol --rpc-url $BASE_SEPOLIA_RPC --broadcast

# ✅ IMPORTANT: Copy the contract addresses from output!
# Add them to your .env file:
# FACTORY_ADDRESS=0x...
# TREASURY_ADDRESS=0x...
# USDC_ADDRESS=0x...

Step 4: Create Live Group

# Create a test group on live testnet
source .env && forge script script/CreateGroup.s.sol --rpc-url $BASE_SEPOLIA_RPC --broadcast

# ✅ Your group is now live at the escrow address shown!
# View on BaseScan: https://sepolia.basescan.org/address/0x...

📊 Real Deployment Costs

Operation Gas Used Cost (ETH) Cost (USD)*
Deploy System 1,967,913 0.000002 ETH $0.008
Create Group 484,254 0.0000005 ETH $0.002
User Deposit ~60,000 0.00000006 ETH $0.0002
Settlement ~80,000 0.00000008 ETH $0.0003

*Based on ETH = $4000, Base gas = 0.001 gwei

💡 Total cost per group payment: ~$0.0005 per user on Base


Testing

Run All Tests

forge test -vv

Test Categories

# Core escrow functionality
forge test --match-contract GroupEscrowTest -vv

# Cashback treasury
forge test --match-contract CashbackTest -vv  

# Invariant/fuzz testing
forge test --match-contract InvariantsTest -vv

# Gas reporting
forge test --gas-report

Contract API

GroupFactory

function createGroup(CreateParams calldata params) external returns (address escrow);

struct CreateParams {
    address merchant;           // Receives funds
    IERC20 token;              // Payment token (USDC)
    uint256 totalAmount;       // Total to collect
    uint256 perUser;           // Amount per participant  
    uint256 deadline;          // Deadline timestamp
    address[] participants;    // Allowlisted addresses
    uint256 cashbackBps;       // Cashback (0-10000 bps)
    address treasury;          // Treasury contract
}

GroupEscrow

// Participant actions
function deposit() external;
function refund() external;

// Settlement
function settle() external;
function enableRefund() external;

// Views
function state() external view returns (State);
function timeRemaining() external view returns (uint256);
function myRequiredAmount() external view returns (uint256);

CashbackTreasury

// Owner functions
function fund(uint256 amount) external;
function withdraw(uint256 amount) external;
function authorizeEscrow(address escrow, bool authorized) external;

// Escrow function
function payoutEqual(IERC20 token, address[] calldata payees, uint256 perUserAmount) external;

State Machine

Pending ──┐
          ├─→ Settled ──→ Closed
          └─→ Refunding ──→ Closed

Pending:    Collecting deposits
Settled:    All paid, funds to merchant + cashback
Refunding:  Past deadline, partial payment
Closed:     Final state

Error Reference

Error Condition
NotParticipant() Caller not in allowlist
AlreadyPaid() Participant deposited twice
WrongAmount() Deposit ≠ perUser
PastDeadline() Action after deadline
NotAllPaid() Settlement with partial payment
NotRefunding() Refund action in wrong state
CashbackUnavailable() Treasury insufficient funds

Gas Optimizations

  • EIP-1167 Clones: ~90% deployment gas savings vs new contracts
  • Unchecked Arithmetic: Safe overflow assumptions where applicable
  • Packed Storage: Efficient state variable layout
  • Bitmap Option: Consider mapping(uint256 => uint256) for large participant sets

Suggested improvements for scale:

// For >20 participants, consider bitmap tracking
mapping(uint256 => uint256) private _paidBitmap;
function _setPaid(address participant, bool paid) private {
    uint256 index = _participantIndex[participant];
    uint256 wordIndex = index / 256;
    uint256 bitIndex = index % 256;
    if (paid) {
        _paidBitmap[wordIndex] |= (1 << bitIndex);
    } else {
        _paidBitmap[wordIndex] &= ~(1 << bitIndex);
    }
}

Security Considerations

  • Reentrancy: nonReentrant on all state-changing functions
  • Integer Overflow: Solidity 0.8+ built-in protection + unchecked where safe
  • Access Control: Participant allowlists, treasury authorization
  • Token Safety: SafeERC20 for all transfers
  • State Validation: Comprehensive state machine checks
  • Deadline Enforcement: Strict timestamp validation

Known Limitations

  • Permit Support: depositWithPermit() marked as TODO pending Base USDC permit verification
  • Participant Limit: Suggested max 20 participants to avoid gas limit issues
  • Single Token: Currently supports one token type per escrow
  • Immutable Params: Group parameters cannot be modified after creation

License

MIT

Contributing

  1. Fork the repository
  2. Create feature branch (git checkout -b feature/amazing-feature)
  3. Add comprehensive tests
  4. Ensure all tests pass (forge test)
  5. Update documentation
  6. Submit pull request

⚠️ Important: This is MVP code. Conduct thorough security audits before mainnet deployment with significant funds.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors