Skip to content

Conversation

@ubinatus
Copy link
Member

Overview

This PR introduces significant improvements to the Raffl Protocol, including a comprehensive VRF recovery system, performance optimizations, security enhancements, and extensive documentation. The changes represent a major version bump to v2.0.0.

📊 Summary Statistics

  • Files Changed: 65 files
  • Additions: +13,066 lines
  • Deletions: -273 lines
  • Net Change: +12,793 lines
  • New Test Files: 10
  • New Documentation Files: 7

🚀 Major Features

1. VRF Recovery System

Problem Solved: Previously, raffles could get permanently stuck if Chainlink VRF requests failed or timed out, leaving user funds locked in the contract.

Solution: Implemented a comprehensive recovery system with two permissionless mechanisms:

Retry VRF Request (retryVRFRequest)

  • Allows anyone to retry a stuck VRF request
  • Available immediately when a raffle is in pending state
  • Creates a new VRF request with updated tracking
  • Emits VRFRequestRetried event for monitoring

Emergency Fail (emergencyFailRaffle)

  • Time-locked recovery mechanism (24-hour timeout)
  • Marks raffle as failed and enables refunds for all participants
  • Permissionless - anyone can trigger after timeout
  • Emits RaffleEmergencyFailed event

Key Changes:

  • Added VRFRequest struct to track request status and timing
  • Added VRFStatus enum (None, Pending, Fulfilled, Failed)
  • New mappings: _raffleVRFRequests and _requestIds
  • Enhanced fulfillRandomWords to handle retry scenarios
  • Comprehensive test coverage (34 new tests)

Documentation Added:

  • VRF-RECOVERY-USER-GUIDE.md - User-friendly guide
  • VRF-RECOVERY-TECHNICAL.md - Developer documentation
  • VRF-RECOVERY-QUICK-REFERENCE.md - Quick reference card
  • VRF-RECOVERY-README.md - Overview and index

2. Performance Optimizations

Storage Layout Optimization

  • Raffl.sol: Reduced from ~17 storage slots to ~11 slots

    • Packed factory, settled, prizesRefunded, gameStatus into single slot
    • Reordered state variables for optimal 32-byte alignment
  • RafflFactory.sol: Optimized struct packing

    • Packed callbackGasLimit, requestConfirmations, nativePayment into one slot
    • Changed VRFRequest.requestTime from uint256 to uint64 (2 slots → 1 slot)
    • Changed ActiveRaffle.deadline from uint256 to uint64 (2 slots → 1 slot)

O(1) Raffle Removal

  • Added _raffleToActiveIndex mapping for O(1) lookup
  • Replaced O(n) linear search with O(1) index lookup in _removeRaffleFromActive
  • Significant gas savings when removing raffles from active list

Storage Read Caching

  • Raffl.sol:

    • Cache entryPrice in buyEntries() to avoid redundant SLOAD
    • Cache entryToken in refundEntries() and _purchaseEntry()
    • Pass cached values to helper functions as parameters
  • RafflFactory.sol:

    • Cache _activeRaffles.length in checkUpkeep() loop
    • Pre-calculate loop iterations to avoid repeated subtraction
    • Use unchecked increment in loops where overflow is impossible

Gas Impact: Reduces gas costs for frequently called functions by minimizing storage reads (SLOAD = 2100 gas cold, 100 gas warm).


3. Security Enhancements

Slither Warning Fixes

  • Renamed requestId parameter to vrfRequestId to avoid shadowing state variable
  • Added SubscriptionConfigUpdated event to handleSubscription() for better monitoring
  • Added indexed parameter to RaffleCreated event for efficient log filtering
  • Updated IRaffl interface with improved NatSpec documentation

Enhanced Error Handling

  • Improved validation checks for prize and entry conditions
  • Better error messages for ETH transfers and token operations in TokenLib
  • Refactored contract modifiers for improved readability

4. Comprehensive Test Suite

Added 10 new test files covering:

  • Access Control (RafflFactory.AccessControl.t.sol) - 467 lines
  • Edge Cases (RafflFactory.EdgeCases.t.sol) - 579 lines
  • VRF Retry (RafflFactory.VRFRetry.t.sol) - 547 lines
  • VRF Retry ERC20 (RafflFactory.VRFRetryERC20.t.sol) - 161 lines
  • Chainlink Exceptions (Raffl.ChainlinkExceptions.t.sol) - 531 lines
  • Disperse Rewards (Raffl.DisperseRewards.t.sol) - 481 lines
  • Fuzz Testing (Raffl.Fuzz.t.sol) - 545 lines
  • Integration Tests (Raffl.Integration.t.sol) - 550 lines
  • Security Tests (Raffl.Security.t.sol) - 622 lines
  • VRF Callback Failure (Raffl.VRFCallbackFailure.t.sol) - 325 lines
  • VRF Edge Cases (Raffl.VRFEdgeCases.t.sol) - 447 lines
  • Entries Edge Cases (Raffl.EntriesEdgeCases.t.sol) - 493 lines
  • Extra Recipient Edge Cases (Raffl.ExtraRecipientEdgeCases.t.sol) - 540 lines
  • ERC721 Prizes (Raffl.ERC721Prizes.t.sol) - 594 lines
  • Token Gating (Raffl.TokenGating.t.sol) - 464 lines

Total New Test Coverage: ~6,500+ lines of comprehensive test cases


5. Documentation

Added comprehensive documentation suite:

  1. PROTOCOL_OVERVIEW.md (1,624 lines)

    • Complete protocol architecture
    • Lifecycle flowcharts
    • Data structures
    • Fee system details
    • Entry system explanation
    • Security features
  2. ENTERPRISE-AUDIT-PREPARATION-SUMMARY.md (699 lines)

    • Audit readiness checklist
    • Security considerations
    • Testing methodology
  3. AUDIT-READINESS-REPORT.md (577 lines)

    • Detailed audit preparation status
    • Code quality metrics
  4. VRF Recovery Documentation (4 files, ~2,100 lines total)

    • User guide
    • Technical documentation
    • Quick reference
    • Overview and index

6. Code Quality Improvements

Solidity Version Upgrade

  • Upgraded from previous version to Solidity 0.8.33 across all contracts
  • Improved compiler optimizations and gas efficiency

Code Refactoring

  • Enhanced contract modifiers with internal functions for better readability
  • Improved loop patterns using length variables
  • Better separation of concerns in helper functions
  • Updated interfaces with comprehensive NatSpec

Dependency Updates

  • Updated bun.lockb with latest dependencies
  • Updated package.json dependencies
  • Upgraded Solidity linter configuration

🔧 Technical Details

Contract Changes

RafflFactory.sol

  • Added VRF recovery system with retry and emergency fail
  • Optimized storage layout (packed structs)
  • Added O(1) raffle removal mechanism
  • Enhanced event emissions for monitoring
  • Improved gas efficiency in checkUpkeep()

Raffl.sol

  • Optimized storage layout (reduced slots)
  • Added storage read caching
  • Enhanced error handling
  • Improved modifier patterns

Interface Updates

  • IRaffl.sol: Added new functions and improved documentation
  • IFactoryFeeManager.sol: Enhanced interface definitions
  • IFeeManager.sol: Updated interface

Error Libraries

  • RafflErrors.sol: Added new error types
  • RafflFactoryErrors.sol: Added VRF-related errors

📝 Breaking Changes

Version Bump

  • Version: Bumped to v2.0.0 across all contracts
  • Indicates major feature additions and improvements

Interface Changes

  • New functions in RafflFactory:
    • retryVRFRequest(address raffle)
    • emergencyFailRaffle(address raffle)
    • getVRFRequestInfo(address raffle)
    • hasVRFRequestTimedOut(address raffle)

Event Changes

  • New events:
    • VRFRequestRetried(address indexed raffle, uint256 indexed requestId)
    • RaffleEmergencyFailed(address indexed raffle)
    • SubscriptionConfigUpdated(...)
  • Enhanced RaffleCreated event with indexed parameter

✅ Testing

Test Coverage

  • Total Tests: 127+ (34 new + 93 existing)
  • Status: ✅ All Passing
  • New Test Categories:
    • VRF recovery scenarios
    • Edge cases and boundary conditions
    • Security vulnerability tests
    • Fuzz testing
    • Integration tests
    • Access control tests

Test Files Modified

  • Updated existing tests to reflect new contract interfaces
  • Enhanced mock contracts (VRFCoordinatorV2PlusMock.sol)
  • Improved test utilities (Common.sol)

🔒 Security Considerations

  1. Time-locked Emergency Fail: 24-hour timeout prevents abuse
  2. Permissionless Recovery: No single point of failure
  3. Strict Validation: All recovery functions have comprehensive checks
  4. Event Monitoring: Full event history for transparency
  5. Test Coverage: Comprehensive security test suite

📦 Dependencies

  • Updated bun.lockb (110,477 → 131,008 bytes)
  • Updated package.json dependencies
  • Solidity version: 0.8.33

🎯 Migration Notes

For Users

  • No action required - all changes are backward compatible for existing raffles
  • New recovery features are available for all raffles created after deployment

For Developers

  • Review new RafflFactory functions for integration
  • Update frontend to handle new events
  • Consider implementing monitoring for VRF recovery events

For Auditors

  • See ENTERPRISE-AUDIT-PREPARATION-SUMMARY.md for detailed audit information
  • All security warnings addressed
  • Comprehensive test coverage provided

📚 Documentation

All documentation is located in the /docs directory:

  • Protocol Overview: PROTOCOL_OVERVIEW.md
  • VRF Recovery: VRF-RECOVERY-README.md (start here)
  • Audit Preparation: ENTERPRISE-AUDIT-PREPARATION-SUMMARY.md
  • Quick Reference: VRF-RECOVERY-QUICK-REFERENCE.md

🚦 Deployment Checklist

  • All tests passing
  • Security warnings addressed
  • Documentation complete
  • Version bumped to v2.0.0
  • Gas optimizations verified
  • Interface changes documented
  • Breaking changes identified

📈 Impact

User Experience

  • ✅ Funds can never be permanently locked
  • ✅ Clear recovery paths for stuck raffles
  • ✅ Better gas efficiency for participants

Developer Experience

  • ✅ Comprehensive documentation
  • ✅ Well-tested codebase
  • ✅ Clear interfaces and events

Protocol Health

  • ✅ Improved security posture
  • ✅ Better gas efficiency
  • ✅ Enhanced monitoring capabilities

🔗 Related Issues

This PR addresses:

  • VRF timeout and failure scenarios
  • Gas optimization opportunities
  • Security audit preparation
  • Documentation gaps
  • Test coverage improvements

📅 Version

v2.0.0 - Major Release


This PR represents a significant milestone in the Raffl Protocol's development, introducing critical recovery mechanisms, performance improvements, and comprehensive documentation to ensure a robust and user-friendly raffle platform.

…ions

- Updated .solhint.json to allow a max line length of 125 and disabled use-natspec.
- Upgraded solhint dependency to version 6.0.2.
- Added new documentation files for VRF recovery, including user guide, quick reference, and technical documentation.
- Enhanced Raffl and RafflFactory contracts to support VRF request tracking, retry functionality, and emergency fail mechanism.
- Introduced new events for VRF request retries and emergency failures.
- Updated tests to cover new VRF retry and emergency fail scenarios.
- Introduced internal functions for modifier checks in Raffl and FactoryFeeManager contracts to improve code readability.
- Added additional validation checks for prize and entry conditions in Raffl and RafflFactory contracts.
- Updated error handling for ETH transfers and token operations in TokenLib to provide clearer revert reasons.
- Refactored loops to use length variables for better performance and clarity.
- Improved test cases to reflect changes in error handling and contract logic.
- Introduced a new documentation file detailing the Raffl Protocol, including an overview, architecture, lifecycle flowchart, data structures, fee system, entry system, external dependencies, security features, supported networks, key constants, and events.
- Enhanced understanding of the protocol's functionality and structure for developers and users.
- Introduced multiple test files covering various aspects of the Raffl protocol, including access control, edge cases, fuzz testing, integration, security, and token gating.
- Enhanced coverage for ownership transfers, fee collection, VRF handling, and entry purchase scenarios.
- Implemented tests for edge cases in prize distribution, entry limits, and token gate requirements.
- Improved overall robustness and reliability of the Raffl protocol through extensive testing.
… Protocol

- Added detailed sections on Chainlink exception handling, including a two-step winner selection process and various exception scenarios.
- Documented gas usage, recovery functions, and the fee system architecture related to VRF requests.
- Improved clarity on token gating, entry systems, and prize requirements, enhancing overall understanding of the protocol's robustness and reliability.
Raffl.sol:
- Pack factory, settled, prizesRefunded, gameStatus into single slot
- Reorder state variables for optimal 32-byte alignment
- Reduce storage from ~17 slots to ~11 slots

RafflFactory.sol:
- Pack callbackGasLimit, requestConfirmations, nativePayment into one slot
- Optimize VRFRequest struct: uint256 requestTime -> uint64 (2 slots instead of 3)
- Optimize ActiveRaffle struct: uint256 deadline -> uint64 (1 slot instead of 2)
- Add _raffleToActiveIndex mapping for O(1) raffle removal
- Replace O(n) linear search with O(1) index lookup in _removeRaffleFromActive
- Rename requestId parameter to vrfRequestId to avoid shadowing state variable
- Add SubscriptionConfigUpdated event to handleSubscription() for better monitoring
- Add indexed parameter to RaffleCreated event for efficient log filtering
- Update IRaffl interface with improved NatSpec documentation
Raffl.sol:
- Cache entryPrice in buyEntries() to avoid redundant SLOAD
- Cache entryToken in refundEntries() and _purchaseEntry()
- Pass cached entryPrice to _purchaseEntry() as parameter
- Cache entryToken in _transferPool() and pass to helper functions
- Update _distributePoolFunds() and _transferTokens() signatures

RafflFactory.sol:
- Add unchecked increment in checkUpkeep() loop
- Cache _activeRaffles.length to avoid repeated SLOAD
- Pre-calculate loop iterations to avoid repeated subtraction

These optimizations reduce gas costs for frequently called functions
by minimizing storage reads (SLOAD = 2100 gas cold, 100 gas warm).
Add detailed documentation for:
- VRF callback out-of-gas scenarios
- VRF never responds (network/subscription issues)
- Automation (checkUpkeep/performUpkeep) failures
- disperseRewards() transfer failures
- Stale VRF response after retry
- LINK subscription issues

Each scenario includes:
- ASCII diagrams showing the failure flow
- State changes (or lack thereof)
- Recovery options with specific function calls
- Edge cases and limitations

Also adds:
- Complete recovery decision tree
- Configuration constants reference
- Monitoring recommendations
@ubinatus ubinatus changed the title feat: add improvements to Raffl Protocol v2 feat: improve Raffl Protocol to v2 Jan 18, 2026
@ubinatus ubinatus self-assigned this Jan 18, 2026
…ling

- Rewrite TokenLib with inline assembly for balanceOf, safeTransfer, safeTransferFrom (~200-600 gas savings per call)
- Add assembly ETH transfers in Raffl._transferEth and refundEntries (~100-200 gas per transfer)
- Optimize event emissions with assembly log2 for EntriesBought (~50-100 gas)
- Cache struct reads in loops (_transferPrizes, _ensureTokenGating) to reduce SLOADs
- Use selector constant instead of string signature in createRaffle prize transfers
- Add assembly keccak256 in nextSalt() (~50-100 gas)
- Optimize checkUpkeep loop with struct caching and block.timestamp caching

All 378 tests pass. Slither analysis shows no new vulnerabilities.
- forge-std: v1.8.1 → v1.14.0
- prettier: 3.7.4 → 3.8.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants