-
Notifications
You must be signed in to change notification settings - Fork 0
feat: implement FilBeam (operator) contract #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Install @openzeppelin/contracts-upgradeable for upgradeable patterns - Install @openzeppelin/contracts for proxy contracts - Update .gitmodules and foundry.lock 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Add custom error definitions in Errors.sol - Add IFWSS interface for payment rail integration - Add MockFWSS contract for testing payment settlements 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Add FilBeam contract with OpenZeppelin upgradeable patterns - Implement Ownable, Initializable, and UUPSUpgradeable - Support usage-based payments for CDN and cache miss scenarios - Add proxy pattern for contract upgrades - Replace constructor with initialize() function for upgradeable pattern - Add _authorizeUpgrade() for UUPS upgrade authorization 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Add 29 test cases covering all contract functionality - Test upgradeable contract patterns and proxy deployment - Test ownership, initialization, and upgrade mechanisms - Test usage reporting and payment settlement flows - Include fuzz testing for usage reporting - Test error conditions and access controls 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Create deployment script with dynamic USDFC decimals detection - Add USD per TiB to USDFC per byte conversion logic - Support environment-based configuration - Add comprehensive deployment logging - Use ERC1967Proxy for upgradeable proxy pattern - Include detailed documentation and usage examples 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Remove Counter.sol, Counter.t.sol, Counter.s.sol - Clean up project to focus on FilBeam functionality - Simplify codebase by removing template files 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Add SPEC.md with project requirements and design - Update AGENTS.md with project context and instructions - Document FilBeam usage-based payments functionality 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Add efficient batch processing for usage rollup reports with gas optimization and atomic transaction guarantees. - Add reportUsageRollupBatch method accepting arrays of dataset IDs, epochs, and usage data - Refactor reportUsageRollup to use internal _reportUsageRollup for code deduplication - Implement atomic batch processing (all succeed or all fail) - Add comprehensive test suite with 10 new test cases covering: * Successful batch reporting across multiple datasets * Array length validation and error handling * Access control and input validation * Atomicity verification with partial failure scenarios * Integration with existing settlement functionality - Update SPEC.md with detailed batch method documentation - Maintain backward compatibility with existing single reporting method Gas efficiency: Batch method reduces transaction costs for bulk operations ideal for rollup workers reporting multiple usage periods.
Enable flexible pricing configuration with decimal precision support for CDN and cache-miss rates. - Add PRICE_DECIMALS environment variable to specify decimal places - Update calculateUsdfcPerByte to handle scaled decimal inputs - Support pricing like $12.50/TiB (1250 with 2 decimals) - Maintain backward compatibility with whole number pricing - Add comprehensive test suite with 9 test cases covering: * Whole number pricing (backward compatibility) * 2-3 decimal place scenarios * High precision pricing * Different token decimal configurations * Edge cases and fuzz testing - Enhanced deployment logging with actual USD price display - Update documentation with new parameter usage examples Examples: - $12.50/TiB: CDN_PRICE_USD_PER_TIB=1250 PRICE_DECIMALS=2 - $9.99/TiB: CDN_PRICE_USD_PER_TIB=999 PRICE_DECIMALS=2 - $10.00/TiB: CDN_PRICE_USD_PER_TIB=10 PRICE_DECIMALS=0
Add gas-efficient batch processing for CDN and cache-miss payment rail settlements with atomic operation guarantees. - Add settleCDNPaymentRailBatch method for bulk CDN settlements - Add settleCacheMissPaymentRailBatch method for bulk cache-miss settlements - Refactor single settlement methods to use internal functions - Implement atomic batch processing (all succeed or all fail) - Add comprehensive test suite with 9 new test cases covering: * Successful batch settlement across multiple datasets * Empty array handling * Error propagation and validation * Atomicity verification with partial failure scenarios * Integration with existing usage reporting - Update SPEC.md with detailed batch settlement documentation - Maintain backward compatibility with existing settlement methods Gas efficiency: Batch methods significantly reduce transaction costs for bulk settlement operations across multiple datasets.
Transform README from basic Foundry template to complete FilBeam project documentation with deployment examples and API reference. - Add project overview highlighting key features - Add detailed deployment guide with environment variable configuration - Add 3 deployment examples for different pricing scenarios: * Decimal pricing ($12.50 CDN, $15.75 cache miss) * Whole dollar pricing ($10 CDN, $15 cache miss) * High precision pricing ($9.995 CDN, $12.750 cache miss) - Add pricing configuration reference table - Add complete contract API documentation covering: * Usage reporting (single and batch methods) * Settlement operations (CDN and cache-miss rails) * Contract management (ownership and upgrades) * View functions for dataset information - Add key concepts section explaining: * Batch operations and atomicity guarantees * Decimal pricing model and token compatibility * Independent settlement rail tracking Provides developers with complete guidance for deploying and interacting with FilBeam contracts.
Remove epochReported mapping and EpochAlreadyReported error. Epoch validation now uses only maxReportedEpoch comparison, reducing gas costs and contract complexity while maintaining duplicate epoch protection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Implements a comprehensive FilBeam smart contract system for usage-based payments in the Filecoin CDN ecosystem, featuring batch processing capabilities and flexible decimal pricing support.
- Upgradeable UUPS proxy contract with independent CDN and cache-miss settlement rails
- Batch operations for gas-efficient usage reporting and settlement processing
- Decimal pricing system supporting fractional USD rates per TiB (e.g., $12.50, $9.99)
Reviewed Changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/FilBeam.sol | Main contract implementation with batch operations and settlement logic |
| src/interfaces/IFWSS.sol | Interface definition for FWSS contract integration |
| src/mocks/MockFWSS.sol | Mock contract for testing FWSS functionality |
| src/Errors.sol | Custom error definitions for contract validation |
| script/DeployFilBeam.s.sol | Deployment script with decimal pricing calculations |
| test/FilBeam.t.sol | Comprehensive test suite covering all contract functionality |
| test/DeployFilBeamDecimalPricing.t.sol | Focused tests for decimal pricing calculations |
| README.md | Updated documentation with API reference and deployment examples |
| SPEC.md | Technical specification document |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
Replace onlyOwner modifier with onlyFilBeamController for usage reporting and payment rail termination functions. Contract initialization now requires filBeamController address parameter. Owner role remains for contract upgrades only.
…d functionality - Add zero-amount check in settlement functions to skip external calls when amount is 0 - Change function parameters from int256 to uint256 for usage reporting - Update UsageReported event to use uint256 instead of int256 - Remove redundant isInitialized flag, use maxReportedEpoch == 0 for initialization check - Add rate update mechanism with setCDNRatePerByte and setCacheMissRatePerByte functions - Add CDNRateUpdated and CacheMissRateUpdated events - Update getDataSetUsage to return 5 values instead of 6 - Update README.md and SPEC.md with API changes Breaking changes: - reportUsageRollup and reportUsageRollupBatch now accept uint256 instead of int256 - getDataSetUsage returns 5 values (removed isInitialized) - UsageReported event emits uint256 values All tests pass (64/64)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 16 out of 17 changed files in this pull request and generated 2 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 16 out of 17 changed files in this pull request and generated 3 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 16 out of 17 changed files in this pull request and generated no new comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
bajtos
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great progress! I have a few more comments to discuss, see below. We also need to decide whether the rollup reports should include fromEpoch, per the discussion above.
src/FilBeamOperator.sol
Outdated
| mapping(uint256 => DataSetUsage) public dataSetUsage; | ||
|
|
||
| event UsageReported( | ||
| uint256 indexed dataSetId, uint256 indexed epoch, uint256 cdnBytesUsed, uint256 cacheMissBytesUsed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am afraid this comment was not addressed yet.
| uint256 indexed dataSetId, uint256 indexed epoch, uint256 cdnBytesUsed, uint256 cacheMissBytesUsed | |
| uint256 indexed dataSetId, uint256 indexed toEpoch, uint256 cdnBytesUsed, uint256 cacheMissBytesUsed |
It would be great to add fromEpoch to the event arguments as well.
| uint256 indexed dataSetId, uint256 indexed epoch, uint256 cdnBytesUsed, uint256 cacheMissBytesUsed | |
| uint256 indexed dataSetId, uint256 indexed fromEpoch, uint256 indexed toEpoch, uint256 cdnBytesUsed, uint256 cacheMissBytesUsed |
src/FilBeamOperator.sol
Outdated
| /// @notice Updates the CDN rate per byte | ||
| /// @dev Can only be called by the contract owner. Rate must be greater than zero. | ||
| /// @param _cdnRatePerByte New CDN rate per byte in smallest token units | ||
| function setCDNRatePerByte(uint256 _cdnRatePerByte) external onlyOwner { | ||
| if (_cdnRatePerByte == 0) revert InvalidRate(); | ||
|
|
||
| uint256 oldRate = cdnRatePerByte; | ||
| cdnRatePerByte = _cdnRatePerByte; | ||
|
|
||
| emit CDNRateUpdated(oldRate, _cdnRatePerByte); | ||
| } | ||
|
|
||
| /// @notice Updates the cache miss rate per byte | ||
| /// @dev Can only be called by the contract owner. Rate must be greater than zero. | ||
| /// @param _cacheMissRatePerByte New cache miss rate per byte in smallest token units | ||
| function setCacheMissRatePerByte(uint256 _cacheMissRatePerByte) external onlyOwner { | ||
| if (_cacheMissRatePerByte == 0) revert InvalidRate(); | ||
|
|
||
| uint256 oldRate = cacheMissRatePerByte; | ||
| cacheMissRatePerByte = _cacheMissRatePerByte; | ||
|
|
||
| emit CacheMissRateUpdated(oldRate, _cacheMissRatePerByte); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you envision the process of changing the rates? Will we ever change only one rate at a time, or will we always change both of them?
Should there be a single method to change both rates atomically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you envision the process of changing the rates?
I envision the process to be manua where transaction is sent from some kind of multisig after we have established new rate as a company.
Will we ever change only one rate at a time, or will we always change both of them?
I don't know but I did not exclude it as a possibility.
Should there be a single method to change both rates atomically?
We can replace two methods with a single one and in case we're changing only one rate we can submit old + new rate in transaction.
src/FilBeamOperator.sol
Outdated
| function getDataSetUsage(uint256 dataSetId) | ||
| external | ||
| view | ||
| returns ( | ||
| uint256 cdnAmount, | ||
| uint256 cacheMissAmount, | ||
| uint256 maxReportedEpoch, | ||
| uint256 lastCDNSettlementEpoch_, | ||
| uint256 lastCacheMissSettlementEpoch_ | ||
| ) | ||
| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Who is going to consume this API, and what data do they need? Is it okay to get amounts waiting for settlement and not egress bytes consumed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good question. Maybe this method is not really needed at the moment.
I don't know if we really need to submit |
- Converting cdnRatePerByte and cacheMissRatePerByte to immutable variables - Removing setCDNRatePerByte() and setCacheMissRatePerByte() functions - Removing CDNRateUpdated and CacheMissRateUpdated events - Updating tests and documentation to reflect immutable rate
Settlement methods now return early instead of reverting when: - Dataset is not initialized (no usage recorded) - No new usage to settle since last settlement This change improves batch operations by allowing them to continue processing other datasets even when some cannot be settled, making the settlement functions idempotent and safer to call repeatedly. Updated tests to verify the new non-reverting behavior and added comprehensive test coverage for silent early returns.
…lify epoch tracking - Remove epoch tracking from settlements (lastCDNSettlementEpoch, lastCacheMissSettlementEpoch) - Simplify settlement events by removing fromEpoch and toEpoch parameters - Add partial settlement support based on payment rail lockupFixed amounts - Implement _getSettleableAmount() to calculate settleable amounts based on rail lockup - Remove getDataSetUsage() getter method (use public mapping directly) - Allow settlements whenever accumulated amounts exist, regardless of new usage reports - Simplify rail validation by checking railId != 0 before settlement attempts
|
As previously discussed with @bajtos, we've made pricing rates immutable, refactored settlements to return early instead of reverting (enabling safer batch operations), and added partial settlement support. Implementing partial settlements has simplified the code by removing epoch validation logic—we no longer check last settled or max reported epochs during settlement. Instead, payment rails can now be settled whenever there's an unsettled amount, regardless of whether there's been a recent usage rollup for the dataset. |
bajtos
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! I like how much simpler the new version is 👏🏻
I am afraid the following comment was not addressed yet, PTAL:
https://github.com/filbeam/contracts/pull/1/files/8cd48abeb8eeeb0066ce8f6f1228af6812c86028..e35cb62544f3e6c54945b7e55c5995385daee0a2#r2405384271
Co-authored-by: Julian Gruber <[email protected]>
src/FilBeamOperator.sol
Outdated
| /// @notice Settles CDN payment rails for multiple data sets | ||
| /// @dev Anyone can call this function to trigger settlement | ||
| /// @param dataSetIds Array of data set IDs to settle | ||
| function settleCDNPaymentRails(uint256[] calldata dataSetIds) external { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
feel free to ignore: What about adding settlePaymentRails() that calls both? I think we can add this later though
src/FilBeamOperator.sol
Outdated
| /// @notice Terminates CDN payment rails for a data set | ||
| /// @dev Can only be called by the FilBeam operator controller | ||
| /// @param dataSetId The data set ID to terminate payment rails for | ||
| function terminateCDNPaymentRails(uint256 dataSetId) external onlyFilBeamOperatorController { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fn names are confusing: terminateCDNPaymentRails() terminates the cdn and cache miss rails, while settleCDNPaymentRails() only settles the cdn rail, not the cache miss rail. When we mean that all types will be settled, can we find a new name, like terminateFilBeamPaymentRails?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've picked terminateCDNPaymentRails method name is to keep it consitent with the one found in FWSS. However terminateFilBeamPaymentRails does sound better but that would also require us to change the contract call inside the terminator worker (which is not a big change as long as we don't forget to do it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what to do here then, happy to follow your lead 👍
- Unify payment rail settlement into one internal method - Move public methods above internal ones
Overview
Introduces FilBeam (operator) contract used for aggregating data set egress usage and settling of CDN-related payment rails inside the FWSS contract.
Core Functions
Usage Reporting (Controller Only)
Settlement (Public)
Management (Owner Only)
Constructor Parameters
fwssAddress- FWSS contract addresscdnRatePerByte- Rate for CDN usagecacheMissRatePerByte- Rate for cache-miss usagefilBeamOperatorController- Authorized reporter addressData Tracking
Each dataset maintains:
Dependencies
Closes filbeam/roadmap#51