Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
5c63bc9
feat: add OpenZeppelin upgradeable contracts dependencies
pyropy Sep 29, 2025
7b15d0e
feat: add FilBeam contract infrastructure
pyropy Sep 29, 2025
d9ea814
feat: implement upgradeable FilBeam contract
pyropy Sep 29, 2025
0b5b4e3
test: add comprehensive FilBeam test suite
pyropy Sep 29, 2025
7b83b93
feat: add deployment script with USDFC integration
pyropy Sep 29, 2025
4f61629
chore: remove unused Counter contract files
pyropy Sep 29, 2025
d6e3eb6
docs: add project specification and update documentation
pyropy Sep 29, 2025
c1e64ed
feat: add batch usage reporting with reportUsageRollupBatch method
pyropy Sep 29, 2025
733c495
feat: add decimal pricing support for deployment script
pyropy Sep 29, 2025
9ea164a
feat: add batch settlement methods for payment rails
pyropy Sep 29, 2025
dd81176
docs: add comprehensive deployment guide and API documentation
pyropy Sep 29, 2025
7f97814
refactor: simplify epoch validation using maxReportedEpoch only
pyropy Sep 29, 2025
2bfb0ab
feat: add filBeamController role for access control
pyropy Sep 30, 2025
b460676
refactor: remove upgradeable pattern and use direct deployment
pyropy Sep 30, 2025
b27c24a
feat: add setFilBeamController method for updating authorized controller
pyropy Sep 30, 2025
567bc87
refactor: make deployer the default owner, remove initialOwner parameter
pyropy Sep 30, 2025
94baf6f
docs: update README with FILBEAM_CONTROLLER and remove proxy references
pyropy Sep 30, 2025
0692c8a
refactor: use InvalidAddress error for zero address validations
pyropy Sep 30, 2025
2ab1bba
Remove OpenZeppelin/openzeppelin-contracts-upgradeable
pyropy Sep 30, 2025
50b3bd9
refactor: improve FilBeam contract with gas optimizations and enhance…
pyropy Sep 30, 2025
b6c7244
Update AGENTS.md
pyropy Sep 30, 2025
e8ba6ab
docs: update README and SPEC to match current contract API
pyropy Oct 1, 2025
c2028ce
chore: Do not validate data set in terminateCDNPaymentRails
pyropy Oct 1, 2025
f2e6e51
chore: Cleanup docs and fix deployment example
pyropy Oct 1, 2025
98f47cd
fix: move last settlement epoch assignment after settlement
pyropy Oct 1, 2025
69814c0
refactor: rename FilBeam to FilBeamOperator and update parameter names
pyropy Oct 7, 2025
7ec4fb6
refactor: rename settleCDNPaymentRails to settleFilBeamPaymentRails
pyropy Oct 7, 2025
1f34058
refactor: remove single operation methods, use batch-only API
pyropy Oct 7, 2025
71db784
refactor: rename batch methods to use plural form
pyropy Oct 7, 2025
5d28a4d
refactor: renamed variable filBeamController to filBeamOperatorContro…
pyropy Oct 7, 2025
e87edf9
feat: read USDFC address from FWSS contract in deployment script
pyropy Oct 7, 2025
ac6abe5
chore: Update README.md deployment example
pyropy Oct 7, 2025
2c6c242
refactor: rename setFilBeamController to setFilBeamOperatorController
pyropy Oct 7, 2025
eed86bc
feat: calculate settlement amounts at report time instead of settlem…
pyropy Oct 7, 2025
7f5870e
chore: update readme
pyropy Oct 7, 2025
8cd48ab
chore: add methods docs
pyropy Oct 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Bash commands
- `forge fmt`: Format the project
- `forge test`: Test the project
- `forge install`: Install dependencies

# Workflow
- Make sure to run `forge fmt` when you're done making a series of test changes
- Prefer running single tests, and not the whole test suite, for performance
- Update [SPEC.md](SPEC.md) and [README.md](README.md) when making changes to the contract API
124 changes: 105 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
## Foundry
# FilBeamOperator Contract

FilBeamOperator is a smart contract used for aggregating CDN and cache-miss usage data and managing payment settlements for CDN payment rails operated by [Filecoin Warm Storage Service](https://github.com/FilOzone/filecoin-services).

**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.**
## Features

Foundry consists of:
- **Usage Reporting**: Batch methods for reporting CDN and cache-miss usage
- **Rail Settlements**: Independent settlement for CDN and cache-miss payment rails
- **Access Control**: Separate roles for contract management and usage reporting

- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools).
- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data.
- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network.
- **Chisel**: Fast, utilitarian, and verbose solidity REPL.
## Foundry

## Documentation
Documentation: https://book.getfoundry.sh/

https://book.getfoundry.sh/
## Prerequisites
- [Foundry](https://getfoundry.sh/) - Ethereum development toolchain

## Usage
### Usage

### Build

Expand All @@ -33,24 +35,108 @@ $ forge test
$ forge fmt
```

### Gas Snapshots
### Deploy FilBeamOperator Contract

```shell
$ forge snapshot
The FilBeamOperator contract requires the following constructor parameters:

```solidity
constructor(
address fwssAddress, // FWSS contract address
uint256 _cdnRatePerByte, // Rate per byte for CDN usage
uint256 _cacheMissRatePerByte, // Rate per byte for cache-miss usage
address _filBeamOperatorController // Address authorized to report usage
)
```

### Anvil
#### Deployment Example

```shell
$ anvil
Deploy the contract using Forge script:

```bash
PRIVATE_KEY=<deployer_private_key> \
FILBEAM_CONTROLLER=<filbeam_controller_address> \
FWSS_ADDRESS=<fwss_contract_address> \
CDN_PRICE_USD_PER_TIB=<cdn_price_usd_per_tib> \
CACHE_MISS_PRICE_USD_PER_TIB=<cache_miss_price_usd_per_tib> \
PRICE_DECIMALS=<price_decimals> \
forge script script/DeployFilBeamOperator.s.sol \
--rpc-url <your_rpc_url> \
--broadcast
```

### Deploy
**Note**: The deployer address automatically becomes the contract owner.

```shell
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>
## Contract API

### Usage Reporting

```solidity
function recordUsageRollups(
uint256[] calldata dataSetIds,
uint256[] calldata epochs,
uint256[] calldata cdnBytesUsed,
uint256[] calldata cacheMissBytesUsed
) external onlyFilBeamOperatorController
```

### Settlement Operations

```solidity
function settleCDNPaymentRails(uint256[] calldata dataSetIds) external
function settleCacheMissPaymentRails(uint256[] calldata dataSetIds) external
```

### Data Set Management

**Payment Rail Termination**
```solidity
function terminateCDNPaymentRails(uint256 dataSetId) external onlyFilBeamOperatorController
```

### Contract Management

**Ownership & Controller**
```solidity
function transferOwnership(address newOwner) external onlyOwner
function setFilBeamOperatorController(address _filBeamOperatorController) external onlyOwner
```

**Rate Management**
```solidity
function setCDNRatePerByte(uint256 _cdnRatePerByte) external onlyOwner
function setCacheMissRatePerByte(uint256 _cacheMissRatePerByte) external onlyOwner
```

### View Functions

**Dataset Information**
```solidity
function getDataSetUsage(uint256 dataSetId) external view returns (
uint256 cdnAmount,
uint256 cacheMissAmount,
uint256 maxReportedEpoch,
uint256 lastCDNSettlementEpoch,
uint256 lastCacheMissSettlementEpoch
)
```

## Key Concepts

### Batch Operations
- **Gas Efficient**: Reduce transaction costs for bulk operations
- **Atomic**: All operations in a batch succeed or all fail
- **Independent Rails**: CDN and cache-miss settlements operate independently

### Pricing Model
- **Usage-Based**: Calculated as `usage_bytes * rate_per_byte` at report time
- **Configurable Rates**: Owner can update rates via `setCDNRatePerByte` and `setCacheMissRatePerByte`
- **Rate Changes**: Rate changes only affect future usage reports, not accumulated non-settled usage amounts

### Rail Settlement
- **Independent Tracking**: CDN and cache-miss settlements tracked separately
- **Epoch-Based**: Settlement periods defined by epoch ranges
- **Accumulative**: Usage accumulates between settlements

### Cast

```shell
Expand Down
200 changes: 200 additions & 0 deletions SPEC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
## Specification

### FilBeamOperator (Operator) Contract

#### Overview

The Filecoin Beam (FilBeamOperator) contract is responsible for managing CDN (cache-hit) and cache-miss data set egress usage data reported by the off-chain rollup worker and settlement of payment rails. Payment rails are managed by the Filecoin Warm Storage Service (FWSS) contract. The FilBeamOperator contract interacts with the FWSS contract to facilitate fund transfers based on reported usage data with rate-based billing.

#### Initialization
**Method**: `constructor(address fwssAddress, uint256 _cdnRatePerByte, uint256 _cacheMissRatePerByte, address _filBeamOperatorController)`

**Parameters**:
- `address fwssAddress`: Address of the FWSS contract
- `uint256 _cdnRatePerByte`: Rate per byte for CDN usage billing (must be > 0)
- `uint256 _cacheMissRatePerByte`: Rate per byte for cache-miss usage billing (must be > 0)
- `address _filBeamOperatorController`: Address authorized to report usage and terminate payment rails

**Owner**:
- The deployer (msg.sender) automatically becomes the contract owner

**Validations**:
- FWSS address cannot be zero address
- Both rates must be greater than zero
- FilBeamOperator controller cannot be zero address

#### Data Structure
**DataSetUsage Struct**:
- `uint256 cdnAmount`: Accumulated CDN settlement amount between settlements (calculated at report time)
- `uint256 cacheMissAmount`: Accumulated cache-miss settlement amount between settlements (calculated at report time)
- `uint256 maxReportedEpoch`: Highest epoch number reported for this dataset (0 indicates uninitialized dataset)
- `uint256 lastCDNSettlementEpoch`: Last epoch settled for CDN payment rail
- `uint256 lastCacheMissSettlementEpoch`: Last epoch settled for cache-miss payment rail

#### Usage Reporting

**Method**: `recordUsageRollups(uint256[] dataSetIds, uint256[] epochs, uint256[] cdnBytesUsed, uint256[] cacheMissBytesUsed)`

- **Access**: FilBeamOperator controller only
- **Purpose**: Accepts multiple usage reports in a single transaction for improved gas efficiency
- **Epoch Requirements**:
- Epoch must be > 0
- Epoch must be greater than previously reported epochs for the dataset
- Each epoch can only be reported once per dataset
- **Usage Requirements**:
- Usage is converted to settlement amounts using current rates at report time
- Amounts accumulate in the dataset between settlements
- **Parameter Requirements**:
- All arrays must have equal length
- **Batch Processing**:
- Processes all reports atomically (all succeed or all fail)
- Maintains epoch ordering and validation rules per dataset
- Prevents duplicate epoch reporting within the batch
- **State Updates**:
- Initialize dataset on first report (sets maxReportedEpoch to non-zero value)
- Calculate amounts: `cdnAmount = cdnBytesUsed * cdnRatePerByte`, `cacheMissAmount = cacheMissBytesUsed * cacheMissRatePerByte`
- Accumulate calculated amounts
- Update max reported epoch
- **Events**: Emits individual `UsageReported` event for each processed report (contains bytes, not amounts)

#### Payment Rail Settlement

**Method**: `settleCDNPaymentRails(uint256[] dataSetIds)`

- **Access**: Publicly callable (anyone can trigger settlement)
- **Purpose**: Settles CDN payment rails for multiple datasets in a single transaction
- **Calculation Period**: From last CDN settlement epoch + 1 to max reported epoch
- **Settlement Logic**:
- Use accumulated CDN amount (calculated at report time)
- Only calls FWSS contract if amount > 0 (gas optimization)
- Reset accumulated CDN amount to zero
- **State Updates**: Update last CDN settlement epoch to max reported epoch
- **Requirements**: Dataset must be initialized and have unreported usage
- **Batch Processing**:
- Processes all settlements atomically (all succeed or all fail)
- Maintains independent operation per dataset
- **Events**: Emits individual `CDNSettlement` event for each processed dataset
- **Independent Operation**: Can be called independently of cache-miss settlement

**Method**: `settleCacheMissPaymentRails(uint256[] dataSetIds)`

- **Access**: Publicly callable (typically called by Storage Providers)
- **Purpose**: Settles cache-miss payment rails for multiple datasets in a single transaction
- **Calculation Period**: From last cache-miss settlement epoch + 1 to max reported epoch
- **Settlement Logic**:
- Use accumulated cache-miss amount (calculated at report time)
- Only calls FWSS contract if amount > 0 (gas optimization)
- Reset accumulated cache-miss amount to zero
- **State Updates**: Update last cache-miss settlement epoch to max reported epoch
- **Requirements**: Dataset must be initialized and have unreported usage
- **Batch Processing**:
- Processes all settlements atomically (all succeed or all fail)
- Maintains independent operation per dataset
- **Events**: Emits individual `CacheMissSettlement` event for each processed dataset
- **Independent Operation**: Can be called independently of CDN settlement

#### Payment Rail Termination
**Method**: `terminateCDNPaymentRails(uint256 dataSetId)`

- **Access**: FilBeamOperator controller only
- **Requirements**: Dataset must be initialized
- **Process**: Forward termination call to FWSS contract
- **Events**: Emits `PaymentRailsTerminated` event

#### Data Access
**Method**: `getDataSetUsage(uint256 dataSetId)`

**Returns**:
- `uint256 cdnAmount`: Current accumulated CDN settlement amount
- `uint256 cacheMissAmount`: Current accumulated cache-miss settlement amount
- `uint256 maxReportedEpoch`: Highest reported epoch (0 indicates uninitialized dataset)
- `uint256 lastCDNSettlementEpoch`: Last CDN settlement epoch
- `uint256 lastCacheMissSettlementEpoch`: Last cache-miss settlement epoch

#### Ownership Management
**Method**: `transferOwnership(address newOwner)`

- **Access**: Contract owner only
- **Requirements**: New owner cannot be zero address
- **Purpose**: Transfer contract ownership

#### FilBeamOperator Controller Management
**Method**: `setFilBeamOperatorController(address _filBeamOperatorController)`

- **Access**: Contract owner only
- **Requirements**: FilBeamOperator controller cannot be zero address
- **Purpose**: Update the authorized address for usage reporting and payment rail termination
- **Events**: Emits `FilBeamOperatorControllerUpdated` event

#### Rate Management
**Method**: `setCDNRatePerByte(uint256 _cdnRatePerByte)`

- **Access**: Contract owner only
- **Requirements**: Rate must be greater than zero
- **Purpose**: Update CDN rate per byte for future settlements
- **Events**: Emits `CDNRateUpdated` event

**Method**: `setCacheMissRatePerByte(uint256 _cacheMissRatePerByte)`

- **Access**: Contract owner only
- **Requirements**: Rate must be greater than zero
- **Purpose**: Update cache-miss rate per byte for future settlements
- **Events**: Emits `CacheMissRateUpdated` event

#### Events
- `UsageReported(uint256 indexed dataSetId, uint256 indexed epoch, uint256 cdnBytesUsed, uint256 cacheMissBytesUsed)`
- `CDNSettlement(uint256 indexed dataSetId, uint256 fromEpoch, uint256 toEpoch, uint256 cdnAmount)`
- `CacheMissSettlement(uint256 indexed dataSetId, uint256 fromEpoch, uint256 toEpoch, uint256 cacheMissAmount)`
- `PaymentRailsTerminated(uint256 indexed dataSetId)`
- `FilBeamOperatorControllerUpdated(address indexed oldController, address indexed newController)`
- `CDNRateUpdated(uint256 oldRate, uint256 newRate)`
- `CacheMissRateUpdated(uint256 oldRate, uint256 newRate)`

#### Access Control
- **Owner**: Address authorized to manage contract ownership, set FilBeamOperator controller, and update rates
- **FilBeamOperator Controller**: Address authorized to report usage and terminate payment rails

#### Error Conditions
- `OwnableUnauthorizedAccount(address)`: Caller is not the contract owner
- `Unauthorized()`: Caller is not the FilBeamOperator controller
- `InvalidEpoch()`: Invalid epoch number or ordering
- `NoUsageToSettle()`: No unreported usage available for settlement
- `InvalidUsageAmount()`: Invalid array lengths in batch operations
- `DataSetNotInitialized()`: Dataset has not been initialized
- `InvalidRate()`: Invalid rate configuration (zero rates)
- `InvalidAddress()`: Invalid address (zero address) provided

### Filecoin Warm Storage Service (FWSS) Contract Interface

**Method**: `settleFilBeamPaymentRails(uint256 dataSetId, uint256 cdnAmount, uint256 cacheMissAmount)`
- **Purpose**: Settle CDN or cache-miss payment rails based on calculated amounts
- **Access**: Callable only by FilBeamOperator contract
- **Parameters**: Either cdnAmount or cacheMissAmount will be zero depending on settlement type

**Method**: `terminateCDNPaymentRails(uint256 dataSetId)`
- **Purpose**: Terminate CDN payment rails for a specific dataset
- **Access**: Callable only by FilBeamOperator contract

### Key Implementation Features

#### Rate-Based Settlement
- Configurable rates per byte for both CDN and cache-miss usage
- Settlement amounts calculated at report time as: `usage * rate`
- Rates set at contract deployment and can be updated by owner via `setCDNRatePerByte` and `setCacheMissRatePerByte`
- Rate changes only affect future usage reports, not accumulated amounts

#### Independent Settlement Rails
- CDN and cache-miss settlements operate independently
- Each rail tracks its own settlement epoch
- Allows flexible settlement patterns for different stakeholders

#### Amount Accumulation
- Settlement amounts (calculated at report time) accumulate between settlements
- Only unsettled amounts are stored in contract state
- Settlement resets accumulated amounts for that rail

#### Epoch Management
- Strict epoch ordering enforcement
- Prevents duplicate epoch reporting
- Supports batched reporting of multiple epochs via `recordUsageRollups` method for gas efficiency
- Independent epoch tracking per dataset
12 changes: 12 additions & 0 deletions foundry.lock
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
{
"lib/openzeppelin-contracts": {
"tag": {
"name": "v5.4.0",
"rev": "c64a1edb67b6e3f4a15cca8909c9482ad33a02b0"
}
},
"lib/forge-std": {
"tag": {
"name": "v1.10.0",
"rev": "8bbcf6e3f8f62f419e5429a0bd89331c85c37824"
}
},
"lib/openzeppelin-contracts-upgradeable": {
"tag": {
"name": "v5.4.0",
"rev": "e725abddf1e01cf05ace496e950fc8e243cc7cab"
}
}
}
Loading