Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ Storage providers submit on-chain transactions on behalf of clients (piece addit

The complete on-chain price catalogue is exposed via `FilecoinWarmStorageServiceStateView.getPriceList()`. It returns a single nested `PriceList` struct covering token, streaming rates, one-time fees, and lockup amounts/periods. See [SPEC.md](SPEC.md) for details on rate calculation, operation fees, pricing updates, and top-up/renewal behavior.

## Service metadata

FilecoinWarmStorageService implements `IFilecoinServiceMetadata`, exposing `name()`, `description()`, and `homepage()` for `eth_call`. Other FOC services are encouraged to use this interface so explorers and clients can identify service operator contracts without hard-coded address maps. `description()` is capped at 256 bytes and should be treated as untrusted display-only text. `homepage()` is an optional URL, capped at 256 bytes, and returns an empty string when not provided. Consumers should validate metadata from unverified contracts and carefully escape all displayed values.

## 🚀 Quick Start

### Prerequisites
Expand Down Expand Up @@ -144,4 +148,3 @@ See [service_contracts/CONTRIBUTING.md](./service_contracts/CONTRIBUTING.md) for

## 📄 License
Dual-licensed under [MIT](https://github.com/FilOzone/filecoin-services/blob/main/LICENSE.md) + [Apache 2.0](https://github.com/FilOzone/filecoin-services/blob/main/LICENSE.md)

1 change: 1 addition & 0 deletions service_contracts/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ check-layout:
# Core contracts we publish ABIs for.
ABI_CONTRACTS := \
FilecoinWarmStorageService \
IFilecoinServiceMetadata \
FilecoinWarmStorageServiceStateLibrary \
FilecoinWarmStorageServiceStateView \
FilecoinPayV1 \
Expand Down
1 change: 1 addition & 0 deletions service_contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This directory contains the smart contracts for different Filecoin services usin
- `src/` - Contract source files
- `FilecoinWarmStorageService.sol` - A service contract with [PDP](https://github.com/FilOzone/pdp) (Proof of Data Possession) and payment integration
- `FilecoinWarmStorageServiceStateView.sol` - View contract for reading `FilecoinWarmStorageService` with `eth_call`.
- `IFilecoinServiceMetadata.sol` - Minimal service identity interface (`name`, `description`, `homepage`)
- `src/lib` - Library source files
- `FilecoinWarmStorageServiceLayout.sol` - Constants conveying the storage layout of `FilecoinWarmStorageService`
- `FilecoinWarmStorageServiceStateInternalLibrary.sol` - `internal` library for embedding logic to read `FilecoinWarmStorageService`
Expand Down
22 changes: 0 additions & 22 deletions service_contracts/abi/Errors.abi.json
Original file line number Diff line number Diff line change
Expand Up @@ -502,28 +502,6 @@
}
]
},
{
"type": "error",
"name": "InvalidServiceDescriptionLength",
"inputs": [
{
"name": "length",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"type": "error",
"name": "InvalidServiceNameLength",
"inputs": [
{
"name": "length",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"type": "error",
"name": "InvalidSignature",
Expand Down
71 changes: 39 additions & 32 deletions service_contracts/abi/FilecoinWarmStorageService.abi.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,19 @@
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "description",
"inputs": [],
"outputs": [
{
"name": "",
"type": "string",
"internalType": "string"
}
],
"stateMutability": "pure"
},
{
"type": "function",
"name": "eip712Domain",
Expand Down Expand Up @@ -372,6 +385,19 @@
],
"stateMutability": "view"
},
{
"type": "function",
"name": "homepage",
"inputs": [],
"outputs": [
{
"name": "",
"type": "string",
"internalType": "string"
}
],
"stateMutability": "pure"
},
{
"type": "function",
"name": "initialize",
Expand All @@ -390,16 +416,6 @@
"name": "_filBeamControllerAddress",
"type": "address",
"internalType": "address"
},
{
"name": "_name",
"type": "string",
"internalType": "string"
},
{
"name": "_description",
"type": "string",
"internalType": "string"
}
],
"outputs": [],
Expand All @@ -418,6 +434,19 @@
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "name",
"inputs": [],
"outputs": [
{
"name": "",
"type": "string",
"internalType": "string"
}
],
"stateMutability": "pure"
},
{
"type": "function",
"name": "nextProvingPeriod",
Expand Down Expand Up @@ -1725,28 +1754,6 @@
"name": "InvalidInitialization",
"inputs": []
},
{
"type": "error",
"name": "InvalidServiceDescriptionLength",
"inputs": [
{
"name": "length",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"type": "error",
"name": "InvalidServiceNameLength",
"inputs": [
{
"name": "length",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"type": "error",
"name": "MaxProvingPeriodZero",
Expand Down
41 changes: 41 additions & 0 deletions service_contracts/abi/IFilecoinServiceMetadata.abi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[
{
"type": "function",
"name": "description",
"inputs": [],
"outputs": [
{
"name": "",
"type": "string",
"internalType": "string"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "homepage",
"inputs": [],
"outputs": [
{
"name": "",
"type": "string",
"internalType": "string"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "name",
"inputs": [],
"outputs": [
{
"name": "",
"type": "string",
"internalType": "string"
}
],
"stateMutability": "view"
}
]
8 changes: 0 additions & 8 deletions service_contracts/src/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,6 @@ library Errors {
/// @param challengeWindowSize The provided challenge window size
error InvalidChallengeWindowSize(uint256 maxProvingPeriod, uint256 challengeWindowSize);

/// @notice The service name length must be >0 and <= 256
/// @param length the attempted length
error InvalidServiceNameLength(uint256 length);

/// @notice The service description length must be >0 and <= 256
/// @param length the attempted length
error InvalidServiceDescriptionLength(uint256 length);

/// @notice This function can only be called by the contract itself during upgrade
/// @param expected The expected caller (the contract address)
/// @param actual The actual caller address
Expand Down
44 changes: 24 additions & 20 deletions service_contracts/src/FilecoinWarmStorageService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {EIP712Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/crypt
import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol";
import {FilecoinPayV1, IValidator} from "@fws-payments/FilecoinPayV1.sol";
import {Errors} from "./Errors.sol";
import {IFilecoinServiceMetadata} from "./IFilecoinServiceMetadata.sol";

import {ServiceProviderRegistry} from "./ServiceProviderRegistry.sol";

Expand Down Expand Up @@ -69,6 +70,7 @@ uint256 constant MAX_TERMINATE_SERVICE_EXTRA_DATA_SIZE = 256; // 256 bytes
/// and adjusts payment rates based on storage size. Also implements validation
/// to reduce payments for faulted epochs.
contract FilecoinWarmStorageService is
IFilecoinServiceMetadata,
PDPListener,
IValidator,
Initializable,
Expand All @@ -79,6 +81,10 @@ contract FilecoinWarmStorageService is
{
// Version tracking
string public constant VERSION = "1.3.0";
string private constant SERVICE_NAME = "Filecoin Warm Storage Service";
string private constant SERVICE_DESCRIPTION =
"Warm storage service for the Filecoin Onchain Cloud. Manages PDP-backed datasets, Filecoin Pay storage rails, lifecycle fees, and optional CDN payment rails.";
Comment thread
rvagg marked this conversation as resolved.
string private constant SERVICE_HOMEPAGE = "https://github.com/FilOzone/filecoin-services";

using Rails for FilecoinPayV1;

Expand Down Expand Up @@ -372,20 +378,15 @@ contract FilecoinWarmStorageService is
}

/**
* @notice Initialize the contract with PDP proving period parameters
* @notice Initialize the contract with PDP proving period parameters.
* @param _maxProvingPeriod Maximum number of epochs between two consecutive proofs
* @param _challengeWindowSize Number of epochs for the challenge window
* @param _filBeamControllerAddress Address authorized to terminate CDN services
* @param _name Service name (max 256 characters, cannot be empty)
* @param _description Service description (max 256 characters, cannot be empty)
*/
function initialize(
uint64 _maxProvingPeriod,
uint256 _challengeWindowSize,
address _filBeamControllerAddress,
string memory _name,
string memory _description
) public initializer {
function initialize(uint64 _maxProvingPeriod, uint256 _challengeWindowSize, address _filBeamControllerAddress)
public
initializer
{
__Ownable_init(msg.sender);
__UUPSUpgradeable_init();
__EIP712_init("FilecoinWarmStorageService", "1");
Expand All @@ -399,21 +400,24 @@ contract FilecoinWarmStorageService is
require(_filBeamControllerAddress != address(0), Errors.ZeroAddress(Errors.AddressField.FilBeamController));
filBeamControllerAddress = _filBeamControllerAddress;

uint256 serviceNameLength = bytes(_name).length;
require(serviceNameLength > 0, Errors.InvalidServiceNameLength(serviceNameLength));
require(serviceNameLength <= 256, Errors.InvalidServiceNameLength(serviceNameLength));

uint256 serviceDescriptionLength = bytes(_description).length;
require(serviceDescriptionLength > 0, Errors.InvalidServiceDescriptionLength(serviceDescriptionLength));
require(serviceDescriptionLength <= 256, Errors.InvalidServiceDescriptionLength(serviceDescriptionLength));

// Emit the FilecoinServiceDeployed event
emit FilecoinServiceDeployed(_name, _description);
emit FilecoinServiceDeployed(SERVICE_NAME, SERVICE_DESCRIPTION);

maxProvingPeriod = _maxProvingPeriod;
challengeWindowSize = _challengeWindowSize;
}

function name() external pure override returns (string memory) {
return SERVICE_NAME;
}

function description() external pure override returns (string memory) {
return SERVICE_DESCRIPTION;
}

function homepage() external pure override returns (string memory) {
return SERVICE_HOMEPAGE;
}

function announceUpgradePlan(address nextImplementation, uint96 delayEpochs) external {
if (delayEpochs == 0) {
delayEpochs = 1;
Expand Down
19 changes: 19 additions & 0 deletions service_contracts/src/IFilecoinServiceMetadata.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
pragma solidity ^0.8.20;

/// @title IFilecoinServiceMetadata
/// @notice Minimal service identity interface for Filecoin Onchain Cloud service contracts.
interface IFilecoinServiceMetadata {
/// @notice Short, human-readable service name.
function name() external view returns (string memory);

/// @notice Concise, human-readable service description.
/// @dev Implementations must limit the UTF-8 encoded value to 256 bytes.
/// Consumers should treat the value as untrusted display-only text.
function description() external view returns (string memory);

/// @notice Optional URL for service documentation, specifications, or source code.
/// @dev Implementations must limit the UTF-8 encoded value to 256 bytes and
/// return an empty string when no homepage is provided.
function homepage() external view returns (string memory);
}
5 changes: 1 addition & 4 deletions service_contracts/test/Abandonment.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,7 @@ contract AbandonmentTest is MockFVMTest {
);
MyERC1967Proxy fwssProxy = new MyERC1967Proxy(
address(fwssImpl),
abi.encodeCall(
FilecoinWarmStorageService.initialize,
(uint64(2880), uint256(60), filBeamController, "Test FWSS", "Abandonment test service")
)
abi.encodeCall(FilecoinWarmStorageService.initialize, (uint64(2880), uint256(60), filBeamController))
);
fwss = FilecoinWarmStorageService(address(fwssProxy));

Expand Down
Loading
Loading