feat: v1.1.0 FWSS upgrade scripts and documentation#384
feat: v1.1.0 FWSS upgrade scripts and documentation#384
Conversation
|
I´m going to attempt following UPGRADE_PROCESS.md and writing down notes here while going through the upgrade process to lurk out initial holes in the documentation. |
|
Steps taken:
|
Deploying new ServiceProviderRegistry implementationFirst setting these:
Then run the
|
|
Struggled for a while to get it verified on Sourcify, but this finally worked after retrying multiple times for some reason:
FilFox verification also worked after brute-force trying it:
|
Deploying new FWSS implementationFirst setting these:
Note: please note that we are using the new SERVICE_PROVIDER_REGISTRY_IMPLEMENTATION_ADDRESS here. Then run the:
Verification on FilFox is constantly failing due to an error in FF |
Announcing planned upgrade of the FWSS contract:Since this is a breaking change, I´m going to set the ability to upgrade the contract (AFTER_EPOCH) to 7 days from now: Then setting these env-vars:
Then running the Countdown timer to the |
Mainnet contract deployments:Deploying new ServiceProviderRegistry implementation to MainnetExporting env-vars:
Deploying FWSS implementation to MainnetFirst setting these: - export ETH_KEYSTORE="/path/to/keystore.json" - export PASSWORD="your-password" - export ETH_RPC_URL=https://api.node.glif.io/rpc/v1Note: please note that we are using the new SERVICE_PROVIDER_REGISTRY_IMPLEMENTATION_ADDRESS here. Then run the: /tools/deploy-warm-storage-implementation-only.sh script: Deploying new FWSS View to MainnetSetting: - export ETH_KEYSTORE="/path/to/keystore.json" - export PASSWORD="your-password" - export ETH_RPC_URL=https://api.node.glif.io/rpc/v1 - export FWSS_PROXY_ADDRESS="0x8408502033C418E1bbC97cE9ac48E5528F371A9f"Then running ./deploy-warm-storage-view.sh Announcing planned upgrade of the FWSS Contract on MainnetSince this is a breaking change, I´m going to set the ability to upgrade the contract (AFTER_EPOCH) to 7 days from now:Setting these:
Then running Countdown timer to the AFTER_EPOCH for which the Mainnet FWSS Contract can be upgraded: https://filecoin.blockscout.com/block/countdown/5709920 |
There was a problem hiding this comment.
Pull request overview
This PR upgrades the FilecoinWarmStorageService and ServiceProviderRegistry contracts to version 1.1.0, along with significant improvements to deployment infrastructure and documentation.
Changes:
- Bumped contract versions from 1.0.0 to 1.1.0 for FWSS and ServiceProviderRegistry with corresponding test updates
- Enhanced deployment scripts with automatic deployments.json integration, network-agnostic chain ID detection, and address persistence
- Added comprehensive upgrade documentation (UPGRADE-PROCESS.md), automated upgrade announcement GitHub workflow, and updated CHANGELOG.md
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| service_contracts/src/FilecoinWarmStorageService.sol | Updated VERSION constant from "1.0.0" to "1.1.0" |
| service_contracts/src/ServiceProviderRegistry.sol | Updated VERSION constant from "1.0.0" to "1.1.0" |
| service_contracts/test/FilecoinWarmStorageService.t.sol | Updated version assertion in test from "1.0.0" to "1.1.0" |
| service_contracts/test/ServiceProviderRegistry.t.sol | Updated version assertion in test from "1.0.0" to "1.1.0" |
| service_contracts/test/ServiceProviderRegistryFull.t.sol | Updated version assertion in test from "1.0.0" to "1.1.0" |
| service_contracts/tools/deploy-warm-storage-implementation-only.sh | Added deployments.json integration, network-specific USDFC token handling, and automatic address persistence |
| service_contracts/tools/deploy-warm-storage-view.sh | Added deployments.json integration and automatic address/metadata persistence |
| service_contracts/tools/set-warm-storage-view.sh | Added deployments.json loading and automatic address/metadata updates |
| service_contracts/tools/deploy-registry.sh | New network-agnostic registry deployment script with implementation-only and full proxy deployment modes |
| service_contracts/tools/deploy-registry-calibnet.sh | Updated to be network-agnostic with auto-detect chain ID and conditional proxy deployment |
| service_contracts/tools/UPGRADE-PROCESS.md | New comprehensive documentation for the two-step upgrade process with phase-based runbook |
| service_contracts/tools/README.md | Updated documentation to reference UPGRADE-PROCESS.md and describe two-step upgrade workflow |
| CHANGELOG.md | Added v1.1.0 release entry with features, breaking changes, bug fixes, and documentation updates |
| .github/workflows/upgrade-announcement.yml | New GitHub Action workflow for automated upgrade announcement issue creation |
| service_contracts/deployments.json | Updated deployment addresses for mainnet (314) and calibnet (314159) with new metadata |
Comments suppressed due to low confidence (1)
service_contracts/tools/deploy-registry-calibnet.sh:219
- The deploy-registry-calibnet.sh file now appears to be a duplicate of deploy-registry.sh. According to the PR description, this file was supposed to be removed since deploy-registry.sh is now network-agnostic. Consider removing this file to avoid confusion and maintenance burden of having two identical scripts.
#!/bin/bash
# deploy-registry-calibnet deploys the Service Provider Registry contract to a target network
# Assumption: ETH_KEYSTORE, PASSWORD, ETH_RPC_URL env vars are set to an appropriate eth keystore path and password
# and to a valid ETH_RPC_URL for the target network.
# Assumption: forge, cast, jq are in the PATH
# Assumption: called from contracts directory so forge paths work out
#
# Get script directory and source deployments.sh
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
source "$SCRIPT_DIR/deployments.sh"
echo "Deploying Service Provider Registry Contract"
WITH_PROXY=false
for arg in "$@"; do
case "$arg" in
--with-proxy)
WITH_PROXY=true
;;
-h|--help)
echo "Usage: $(basename "$0") [--with-proxy]"
echo ""
echo "Default: deploy implementation only (upgrade-first)."
echo " --with-proxy Also deploy a new proxy and initialize it."
exit 0
;;
*)
echo "Error: Unknown option '$arg'"
echo "Run with --help for usage."
exit 1
;;
esac
done
if [ "$WITH_PROXY" = "true" ]; then
echo "Mode: implementation + proxy deployment"
else
echo "Mode: implementation-only deployment (upgrade-first)"
fi
if [ -z "$ETH_RPC_URL" ]; then
echo "Error: ETH_RPC_URL is not set"
exit 1
fi
# Auto-detect chain ID from RPC if not already set
if [ -z "$CHAIN" ]; then
export CHAIN=$(cast chain-id)
if [ -z "$CHAIN" ]; then
echo "Error: Failed to detect chain ID from RPC"
exit 1
fi
fi
# Load deployment addresses from deployments.json
load_deployment_addresses "$CHAIN"
if [ -z "$ETH_KEYSTORE" ]; then
echo "Error: ETH_KEYSTORE is not set"
exit 1
fi
# Optional: Check if PASSWORD is set (some users might use empty password)
if [ -z "$PASSWORD" ]; then
echo "Warning: PASSWORD is not set, using empty password"
fi
ADDR=$(cast wallet address --password "$PASSWORD")
echo "Deploying contracts from address $ADDR"
# Get current balance and nonce (cast will use ETH_RPC_URL)
BALANCE=$(cast balance "$ADDR")
echo "Deployer balance: $BALANCE"
NONCE="$(cast nonce "$ADDR")"
echo "Starting nonce: $NONCE"
# Deploy ServiceProviderRegistry implementation
echo ""
echo "=== STEP 1: Deploying ServiceProviderRegistry Implementation ==="
SERVICE_PROVIDER_REGISTRY_IMPLEMENTATION_ADDRESS=$(forge create --password "$PASSWORD" --broadcast --nonce $NONCE src/ServiceProviderRegistry.sol:ServiceProviderRegistry --optimizer-runs 1 --via-ir | grep "Deployed to" | awk '{print $3}')
if [ -z "$SERVICE_PROVIDER_REGISTRY_IMPLEMENTATION_ADDRESS" ]; then
echo "Error: Failed to extract ServiceProviderRegistry implementation address"
exit 1
fi
echo "✓ ServiceProviderRegistry implementation deployed at: $SERVICE_PROVIDER_REGISTRY_IMPLEMENTATION_ADDRESS"
NONCE=$(expr $NONCE + "1")
if [ "$WITH_PROXY" = "true" ]; then
# Deploy ServiceProviderRegistry proxy
echo ""
echo "=== STEP 2: Deploying ServiceProviderRegistry Proxy ==="
# Initialize with no parameters for basic initialization
INIT_DATA=$(cast calldata "initialize()")
echo "Initialization calldata: $INIT_DATA"
REGISTRY_PROXY_ADDRESS=$(forge create --password "$PASSWORD" --broadcast --nonce $NONCE lib/pdp/src/ERC1967Proxy.sol:MyERC1967Proxy --constructor-args $SERVICE_PROVIDER_REGISTRY_IMPLEMENTATION_ADDRESS $INIT_DATA --optimizer-runs 1 --via-ir | grep "Deployed to" | awk '{print $3}')
if [ -z "$REGISTRY_PROXY_ADDRESS" ]; then
echo "Error: Failed to extract ServiceProviderRegistry proxy address"
exit 1
fi
echo "✓ ServiceProviderRegistry proxy deployed at: $REGISTRY_PROXY_ADDRESS"
# Verify deployment by calling version() on the proxy
echo ""
echo "=== STEP 3: Verifying Deployment ==="
VERSION=$(cast call $REGISTRY_PROXY_ADDRESS "version()(string)")
if [ -z "$VERSION" ]; then
echo "Warning: Could not verify contract version"
else
echo "✓ Contract version: $VERSION"
fi
# Get registration fee
FEE=$(cast call $REGISTRY_PROXY_ADDRESS "REGISTRATION_FEE()(uint256)")
if [ -z "$FEE" ]; then
echo "Warning: Could not retrieve registration fee"
FEE_IN_FIL="unknown"
else
echo "✓ Registration fee: $FEE attoFIL"
FEE_IN_FIL="$FEE attoFIL"
fi
# Get burn actor address
BURN_ACTOR=$(cast call $REGISTRY_PROXY_ADDRESS "BURN_ACTOR()(address)")
if [ -z "$BURN_ACTOR" ]; then
echo "Warning: Could not retrieve burn actor address"
else
echo "✓ Burn actor address: $BURN_ACTOR"
fi
# Get contract version (this should be used instead of hardcoded version)
CONTRACT_VERSION=$(cast call $REGISTRY_PROXY_ADDRESS "VERSION()(string)")
if [ -z "$CONTRACT_VERSION" ]; then
echo "Warning: Could not retrieve contract version"
CONTRACT_VERSION="Unknown"
fi
else
echo ""
echo "=== STEP 2: Skipping Proxy Deployment ==="
echo "Use --with-proxy to deploy and initialize a new proxy."
CONTRACT_VERSION="n/a"
FEE_IN_FIL="n/a"
BURN_ACTOR="n/a"
fi
# Summary of deployed contracts
echo ""
echo "=========================================="
echo "=== DEPLOYMENT SUMMARY ==="
echo "=========================================="
echo "ServiceProviderRegistry Implementation: $SERVICE_PROVIDER_REGISTRY_IMPLEMENTATION_ADDRESS"
if [ "$WITH_PROXY" = "true" ]; then
echo "ServiceProviderRegistry Proxy: $REGISTRY_PROXY_ADDRESS"
fi
echo "=========================================="
# Update deployments.json
if [ -n "$SERVICE_PROVIDER_REGISTRY_IMPLEMENTATION_ADDRESS" ]; then
update_deployment_address "$CHAIN" "SERVICE_PROVIDER_REGISTRY_IMPLEMENTATION_ADDRESS" "$SERVICE_PROVIDER_REGISTRY_IMPLEMENTATION_ADDRESS"
fi
if [ "$WITH_PROXY" = "true" ] && [ -n "$REGISTRY_PROXY_ADDRESS" ]; then
update_deployment_address "$CHAIN" "SERVICE_PROVIDER_REGISTRY_PROXY_ADDRESS" "$REGISTRY_PROXY_ADDRESS"
fi
if [ -n "$SERVICE_PROVIDER_REGISTRY_IMPLEMENTATION_ADDRESS" ] || [ -n "$REGISTRY_PROXY_ADDRESS" ]; then
update_deployment_metadata "$CHAIN"
fi
echo ""
echo "Contract Details:"
echo " - Version: $CONTRACT_VERSION"
echo " - Registration Fee: $FEE_IN_FIL (burned)"
echo " - Burn Actor: $BURN_ACTOR"
CHAIN_LABEL="unknown"
if [ "$CHAIN" = "314159" ]; then
CHAIN_LABEL="Calibration testnet (314159)"
elif [ "$CHAIN" = "314" ]; then
CHAIN_LABEL="Filecoin mainnet (314)"
else
CHAIN_LABEL="Chain ID $CHAIN"
fi
echo " - Chain: $CHAIN_LABEL"
echo ""
echo "Next steps:"
if [ "$WITH_PROXY" = "true" ]; then
echo "1. Save the proxy address: export REGISTRY_ADDRESS=$REGISTRY_PROXY_ADDRESS"
echo "2. Verify the deployment by calling getProviderCount() - should return 0"
echo "3. Test registration with: cast send --value <registration_fee>attoFIL ..."
echo "4. Transfer ownership if needed using transferOwnership()"
echo "5. The registry is ready for provider registrations"
else
echo "1. Save the implementation address for upgrade announcement"
echo "2. Proceed with announce-planned-upgrade-registry.sh"
fi
echo ""
if [ "$WITH_PROXY" = "true" ]; then
echo "To interact with the registry:"
echo " View functions:"
echo " cast call $REGISTRY_PROXY_ADDRESS \"getProviderCount()(uint256)\""
echo " cast call $REGISTRY_PROXY_ADDRESS \"getAllActiveProviders()(uint256[])\""
echo " State changes (requires registration fee):"
echo " Register as provider (requires proper encoding of PDPData)"
echo ""
fi
# Automatic contract verification
if [ "${AUTO_VERIFY:-true}" = "true" ]; then
echo
echo "🔍 Starting automatic contract verification..."
pushd "$(dirname $0)/.." >/dev/null
source tools/verify-contracts.sh
verify_contracts_batch "$SERVICE_PROVIDER_REGISTRY_IMPLEMENTATION_ADDRESS,src/ServiceProviderRegistry.sol:ServiceProviderRegistry"
popd >/dev/null
else
echo
echo "⏭️ Skipping automatic verification (export AUTO_VERIFY=true to enable)"
fi
echo "=========================================="
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@rjan90 we seem to be missing a step - you deployed a new view contract but FWSS still points to the old: You need to set it on FWSS: Same for calib. The new one just removes some methods so this isn't critical or fatal, we're just tightening up the workflow. Also puts the pressure on us to tag a new synapse because we expose some utility versions of the removed methods, I just don't know if anyone actually uses them anywhere. |
I was planning to set it after the upgrade, since it is a breaking change: #395 (reply in thread). At least from what I could see in the |
BigLep
left a comment
There was a problem hiding this comment.
Thanks for working all this through @rjan90 and cleaning stuff up. You don't need to incorporate all my comments. These were the things that came to mind in trying to understand the process. It would probably be useful for me to look at a fresh head, but wanted to get some initial thoughts out in case it helps with 2026-01-22 conversation.
| See [`service_contracts/deployments.json`](./service_contracts/deployments.json) for current Mainnet (chain 314) and Calibnet (chain 314159) contract addresses. | ||
|
|
||
| ### Added | ||
| - `ProviderIdSet` contract for efficient provider ID management ([#386](https://github.com/FilOzone/filecoin-services/pull/386)) |
There was a problem hiding this comment.
I think we should talk more about how this is being used within FOC (i.e., "endorsed SP to meet GA durability story"). Basically we have a generic contract for storing a set of ids and we've blessed one particular instance of the contract to be the "endorsed set of provider ids".
|
|
||
| See [`service_contracts/deployments.json`](./service_contracts/deployments.json) for current Mainnet (chain 314) and Calibnet (chain 314159) contract addresses. | ||
|
|
||
| ### Added |
There was a problem hiding this comment.
Not required, but it might be useful to separate which things are useful for consumers vs. maintainers.
| - `WARM_STORAGE_PROXY_ADDRESS` → `FWSS_PROXY_ADDRESS` | ||
| - `WARM_STORAGE_VIEW_ADDRESS` → `FWSS_VIEW_ADDRESS` | ||
| - Added `SIGNATURE_VERIFICATION_LIB_ADDRESS` | ||
| - **BREAKING**: Rail settlement required before dataset deletion ([#377](https://github.com/FilOzone/filecoin-services/pull/377)) |
There was a problem hiding this comment.
Given we fundamentally changed an API, should this be a major version bump? (Maybe this gets to documenting how we're mapping semver to this...)
There was a problem hiding this comment.
Yeah .. good point; but what is the scope that we have to consider for this? since we have separate repos we're going to have to tag the ones not in here separately and then lump everything else together for a semver
I'm fine with proper semver for this but it's going to come as a surprise to people, we'll just have to tell them we're following semver so any breaking change is going to get a semver-major and feature addition a minor. In this change set we have two breakages from this repo, you could argue 3:
- Settlement required before deletion, breakage signal matters here for downstream clients that want to perform deletion - in practice it's entirely manageable by us but it's a reasonable signal
- Removal of the unnecessary methods off the view contract - in this case the SDK has accessors for them and those won't work anymore, so it's real breakage
- Moving the modifyRail into AddPieces - this one's not clearly breakage, but you could make the argument for it because the user has to start paying at a different point and maybe there's some person or software out there that makes assumptions about rail state that this impacts (very doubtful, but possible)
So, if you want to pull the 2.0.0 trigger I'm behind that, but it'll require communication.
|
Other 2026-01-22 things that either came up in conversation or slack...
|
…ults and persist deployment metadata
…nd persist metadata
…atibility and chain ID handling refactor: enhance deploy-registry-calibnet.sh for better network compatibility and chain ID handling
…m-storage-implementation-only.sh
…nWarmStorageService tests
docs: update upgrade-process document
…and action requirements
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Integrated into deploy-registry.sh which is network agnositc
chore: make implementation "mode" wording clearer
chore: rename workflow to `create-upgrade-announcement-issue.yml`
fix: address `UPGRADE-PROCESS` comments
Co-authored-by: Steve Loeppky <biglep@filoz.org>
Co-authored-by: Steve Loeppky <biglep@filoz.org>
fix: update migrate data handling in upgrade script
This reverts commit 85ee423.
fix: incorporate PR feedback in UPGRADE-PROCESS.md
fix: notify stakeholders
593e57a to
4191992
Compare
Move the issue creation logic from inline workflow JavaScript to a separate script at .github/scripts/create-upgrade-announcement.js.
|
Until FilOzone/synapse-sdk#567 is implemented, we'll need to have a manual step about updating Synapse after a contract release. |
- Update script to generate combined release issue with user-facing info at top and release engineer checklist below (Lotus-style) - Simplify UPGRADE-PROCESS.md to focus on FWSS as the primary path - Move ServiceProviderRegistry and StateView to separate "Upgrading Other Contracts" section since they are rarely upgraded - Remove upgrade_fwss workflow input (FWSS always included) - Mark Registry/StateView inputs as "(Rare)" in workflow - Align script section headers with UPGRADE-PROCESS.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
I think it would be useful to look at what sucessful script or github action run for mainnet and calibration look like (without having to parse the JS logic). I didn't see a successful run at https://github.com/FilOzone/filecoin-services/actions/workflows/create-upgrade-announcement-issue.yml
I did a quick pass through previous comments. This one still seemed relevant: #384 (comment)
service_contracts/tools/README.md
Outdated
| ### Available Scripts | ||
| ### Deployment Scripts | ||
|
|
||
| - `deploy-warm-storage-calibnet.sh` - Deploy FilecoinWarmStorageService only (requires existing PDPVerifier and FilecoinPayV1 contracts) |
There was a problem hiding this comment.
Clarify if this only deploys to calbiration?
Make clear if this is deploying a proxy and implementation?
(Side: this is where the table idea from https://github.com/FilOzone/filecoin-services/pull/384/changes#r2715169096 I think could be helpful.)
| ### Deployment Scripts | ||
|
|
||
| - `deploy-warm-storage-calibnet.sh` - Deploy FilecoinWarmStorageService only (requires existing PDPVerifier and FilecoinPayV1 contracts) | ||
| - `deploy-warm-storage-implementation-only.sh` - Deploy FWSS implementation only; loads defaults from `deployments.json` and writes back new implementation + metadata (reuses existing signature lib unless redeployed) |
There was a problem hiding this comment.
What networks does it deploy to? I'm asking given some scripts specify a network name in the file name.
There was a problem hiding this comment.
It can deploy to both. I´m fixing up a lot of the naming issues with regards to the scripts in a PR ontop of this: #414
chore: address PR review comments
Closes: #346, #358, #393, #394
Kind of a large PR, that expanded in size due to encountering issues with scripts along the way. But high-level changes are:
Version updates
FilecoinWarmStorageService: 1.0.0 → 1.1.0ServiceProviderRegistry: 1.0.0 → 1.1.0Deployment infrastructure
deployments.jsonand persist new addresses to some scripts I used during the upgrade.Script enhancements
deploy-warm-storage-implementation-only.sh:deploy-warm-storage-view.sh:set-warm-storage-view.sh:deploy-registry.shGitHub workflow
Documentation