Shared Libraries
Core libraries providing foundational functionality, data structures, and utilities used across all TokenOps vesting contracts. These libraries ensure consistency, efficiency, and maintainability throughout the system.
📚 Available Libraries
Core Computational Libraries
library TokenVestingLib {
    struct Vesting { /* ... */ }
    function calculateVestedAmount(Vesting memory, uint32) pure returns (uint256);
}
Central library containing vesting calculations and data structures. Provides gas-optimized algorithms for all vesting computations across the system.
Access Control Libraries
abstract contract AccessProtected {
    enum AdminRole { None, Standard, Super }
    modifier onlyAdmin() { /* ... */ }
}
Multi-admin access control system with role-based permissions and emergency controls for secure administrative operations.
Error Management Libraries
library Errors {
    error InvalidRecipient();
    error VestingNotFound();
    error InsufficientFunding();
}
Centralized error definitions providing standardized, gas-efficient error handling across all contracts.
Fee Management Libraries
abstract contract FactoryFeeManager {
    enum FeeType { Gas, DistributionToken }
    function getFeeConfig(address) returns (FeeType, uint256);
}
Sophisticated fee management for factory contracts with support for custom fee structures and flexible collection mechanisms.
🎯 Library Overview
TokenVestingLib - Core Computations
Purpose: Mathematical foundation for all vesting operations Key Features:
- Gas-optimized vesting calculations
- Packed struct design for storage efficiency
- Support for complex vesting schedules (cliff, linear, initial unlock)
- Consistent calculation logic across all manager types
Usage Example:
using TokenVestingLib for TokenVestingLib.Vesting;
function getVestedAmount(bytes32 vestingId) public view returns (uint256) {
    return vestings[vestingId].calculateVestedAmount(uint32(block.timestamp));
}
AccessProtected - Security Framework
Purpose: Role-based access control and security management Key Features:
- Multi-admin support with hierarchical roles
- Emergency pause/unpause capabilities
- Secure admin role management
- Event-driven transparency
Usage Example:
contract MyVestingManager is AccessProtected {
    constructor() AccessProtected(msg.sender) {}
    function createVesting() external onlyAdmin whenNotPaused {
        // Admin-only function with pause protection
    }
}
Errors - Standardized Error Handling
Purpose: Centralized, gas-efficient error management Key Features:
- Custom errors instead of string-based reverts
- Categorized by functional domain
- Parameterized errors for better debugging
- Significant gas savings on deployment and execution
Usage Example:
function claimVesting(bytes32 vestingId) external {
    if (vestings[vestingId].recipient != msg.sender) {
        revert Errors.NotAuthorized();
    }
    if (claimableAmount == 0) {
        revert Errors.NoTokensAvailable();
    }
}
FactoryFeeManager - Fee Collection System
Purpose: Flexible fee management for factory-deployed contracts Key Features:
- Dual fee types (gas-based and token-based)
- Custom fee configurations per deployer
- Automatic fee collection and distribution
- Volume-based discounts and tier systems
Usage Example:
contract VestingFactory is FactoryFeeManager {
    function deployManager(address token) external payable {
        collectGasFee(msg.sender);
        // Deploy with fee configuration
    }
}
🔧 Integration Patterns
Combined Usage
Most vesting contracts use multiple libraries together:
contract TokenVestingManager is AccessProtected {
    using TokenVestingLib for TokenVestingLib.Vesting;
    mapping(bytes32 => TokenVestingLib.Vesting) public vestings;
    function createVesting(
        address recipient,
        uint256 amount,
        uint32 duration
    ) external onlyAdmin returns (bytes32) {
        if (recipient == address(0)) {
            revert Errors.InvalidRecipient();
        }
        bytes32 vestingId = keccak256(abi.encodePacked(recipient, amount, block.timestamp));
        vestings[vestingId] = TokenVestingLib.Vesting({
            recipient: recipient,
            startTimestamp: uint32(block.timestamp),
            endTimestamp: uint32(block.timestamp + duration),
            // ... other fields
        });
        return vestingId;
    }
    function claim(bytes32 vestingId) external {
        TokenVestingLib.Vesting storage vesting = vestings[vestingId];
        if (vesting.recipient != msg.sender) {
            revert Errors.NotAuthorized();
        }
        uint256 vested = vesting.calculateVestedAmount(uint32(block.timestamp));
        uint256 claimable = vested - vesting.claimedAmount;
        if (claimable == 0) {
            revert Errors.NoTokensAvailable();
        }
        vesting.claimedAmount += claimable;
        // Transfer tokens...
    }
}
Factory Integration Pattern
contract VestingManagerFactory is AccessProtected, FactoryFeeManager {
    constructor(
        address feeCollector,
        uint256 defaultGasFee,
        uint256 defaultTokenFee
    )
        AccessProtected(msg.sender)
        FactoryFeeManager(feeCollector, defaultGasFee, defaultTokenFee)
    {}
    function deployVestingManager(
        address token
    ) external payable onlyAdmin returns (address) {
        // Collect deployment fee
        collectGasFee(msg.sender);
        // Get fee configuration for the deployed manager
        (ITypes.FeeType feeType, uint256 fee) = getFeeConfig(msg.sender);
        // Deploy with proper configuration
        TokenVestingManager manager = new TokenVestingManager(
            token,
            feeType,
            fee,
            feeCollector
        );
        // Transfer admin privileges
        manager.transferAdmin(msg.sender);
        return address(manager);
    }
}
📊 Library Comparison
| Library | Purpose | Gas Impact | Complexity | Dependencies | 
|---|---|---|---|---|
| TokenVestingLib | Core calculations | High savings | Medium | None | 
| AccessProtected | Access control | Medium cost | Low | None | 
| Errors | Error handling | High savings | Low | None | 
| FactoryFeeManager | Fee management | Medium cost | High | AccessProtected | 
🚀 Quick Start
Basic Manager Implementation
pragma solidity ^0.8.19;
import {AccessProtected} from "./libraries/AccessProtected.sol";
import {TokenVestingLib} from "./libraries/TokenVestingLib.sol";
import {Errors} from "./libraries/Errors.sol";
contract BasicVestingManager is AccessProtected {
    using TokenVestingLib for TokenVestingLib.Vesting;
    mapping(bytes32 => TokenVestingLib.Vesting) public vestings;
    constructor(address initialAdmin) AccessProtected(initialAdmin) {}
    function createVesting(
        TokenVestingLib.VestingParams memory params
    ) external onlyAdmin returns (bytes32) {
        if (params._recipient == address(0)) {
            revert Errors.InvalidRecipient();
        }
        vestings[params._vestingId] = TokenVestingLib.Vesting({
            recipient: params._recipient,
            startTimestamp: params._startTimestamp,
            endTimestamp: params._endTimestamp,
            // ... other fields from params
        });
        return params._vestingId;
    }
    function getVestedAmount(bytes32 vestingId) external view returns (uint256) {
        return vestings[vestingId].calculateVestedAmount(uint32(block.timestamp));
    }
}
Factory Implementation
contract VestingFactory is AccessProtected, FactoryFeeManager {
    constructor()
        AccessProtected(msg.sender)
        FactoryFeeManager(
            msg.sender,     // Fee collector
            0.001 ether,    // Default gas fee
            100             // Default token fee (1%)
        )
    {}
    function deployBasicManager(
        address token
    ) external payable returns (BasicVestingManager) {
        collectGasFee(msg.sender);
        BasicVestingManager manager = new BasicVestingManager(msg.sender);
        emit ManagerDeployed(address(manager), msg.sender);
        return manager;
    }
    event ManagerDeployed(address indexed manager, address indexed deployer);
}
🛡️ Security Considerations
Library Security
TokenVestingLib
- Pure functions - No state modifications, safe for all contexts
- Input validation - Calling contracts must validate inputs
- Overflow protection - Uses Solidity 0.8+ built-in protection
- Precision handling - Conservative calculations prevent over-vesting
AccessProtected
- Admin lockout prevention - Cannot remove last admin
- Role validation - Proper role checking in all functions
- Emergency controls - Pause mechanisms for security incidents
- Event logging - All admin changes logged for transparency
Errors
- Information leakage - No sensitive data in error messages
- Gas efficiency - Custom errors reduce deployment and runtime costs
- Consistency - Standardized error types across system
FactoryFeeManager
- Fee validation - Maximum fee limits prevent abuse
- Access control - Admin-only fee configuration
- Payment verification - Proper fee collection before services
- Refund mechanisms - Excess payments automatically refunded
Integration Security
Common Patterns
// Good: Proper input validation
function createVesting(address recipient, uint256 amount) external onlyAdmin {
    if (recipient == address(0)) revert Errors.InvalidRecipient();
    if (amount == 0) revert Errors.ZeroAmount();
    // Proceed with creation
}
// Bad: Missing validation
function createVesting(address recipient, uint256 amount) external onlyAdmin {
    // Direct creation without validation
}
Error Handling
// Good: Specific errors with context
if (amount > maxAllowed) {
    revert Errors.AmountExceedsMaximum(amount, maxAllowed);
}
// Bad: Generic errors
if (amount > maxAllowed) {
    revert Errors.InvalidInput();
}
📈 Performance Optimization
Gas Optimization Strategies
Storage Layout
// Optimized: Pack related fields together
struct Vesting {
    address recipient;          // 20 bytes
    uint32 startTimestamp;     // 4 bytes  | Same slot
    uint32 endTimestamp;       // 4 bytes  | Same slot
    uint32 cliffTimestamp;     // 4 bytes  | Same slot
    uint256 amount;            // 32 bytes | New slot
}
Calculation Efficiency
// Optimized: Single calculation with memory parameter
uint256 vested = vesting.calculateVestedAmount(uint32(block.timestamp));
// Less optimal: Multiple storage reads
uint256 vested = calculateVested(vestingId, block.timestamp);
Error Handling
// Optimized: Custom errors
if (invalid) revert Errors.InvalidInput();
// Less optimal: String errors
require(!invalid, "Invalid input parameter");
🔄 Upgrade Considerations
Library Versioning
Libraries should be versioned for compatibility:
// contracts/libraries/v1/TokenVestingLib.sol
library TokenVestingLibV1 {
    // Version 1 implementation
}
// contracts/libraries/v2/TokenVestingLib.sol
library TokenVestingLibV2 {
    // Version 2 with new features
}
Migration Strategies
Data Structure Evolution
// V1 Vesting struct
struct VestingV1 {
    address recipient;
    uint256 amount;
    uint32 startTime;
}
// V2 Vesting struct with additional fields
struct VestingV2 {
    address recipient;
    uint256 amount;
    uint32 startTime;
    uint32 cliffTime;     // New field
    bool isRevocable;     // New field
}
// Migration function
function migrateVesting(bytes32 vestingId) external {
    VestingV1 memory oldVesting = oldVestings[vestingId];
    newVestings[vestingId] = VestingV2({
        recipient: oldVesting.recipient,
        amount: oldVesting.amount,
        startTime: oldVesting.startTime,
        cliffTime: 0,           // Default value
        isRevocable: true       // Default value
    });
}
📋 Best Practices
Development Guidelines
- Import specific items instead of entire libraries
- Use library functions consistently across similar operations
- Validate inputs before calling library functions
- Handle errors appropriately with specific error types
- Test edge cases thoroughly, especially for calculations
- Document library usage in your contracts
- Monitor gas costs when using complex library functions
Code Organization
// Good: Clear imports and usage
import {TokenVestingLib} from "./libraries/TokenVestingLib.sol";
import {Errors} from "./libraries/Errors.sol";
contract VestingManager {
    using TokenVestingLib for TokenVestingLib.Vesting;
    function processVesting(bytes32 id) external {
        if (vestings[id].recipient == address(0)) {
            revert Errors.InvalidVestingId();
        }
        uint256 amount = vestings[id].calculateVestedAmount(uint32(block.timestamp));
        // Process amount...
    }
}
Testing Approach
contract LibraryTest {
    function testVestingCalculation() public {
        TokenVestingLib.Vesting memory vesting = createTestVesting();
        uint256 vested = vesting.calculateVestedAmount(uint32(block.timestamp));
        assertEq(vested, expectedAmount);
    }
    function testErrorHandling() public {
        vm.expectRevert(Errors.InvalidRecipient.selector);
        manager.createVesting(address(0), 1000);
    }
}
The shared libraries form the backbone of the TokenOps vesting system, providing consistent, efficient, and secure functionality across all contracts while maintaining flexibility for different use cases and deployment patterns.