feat: Make FilBeamOperator contract upgradeable#13
feat: Make FilBeamOperator contract upgradeable#13Chaitu-Tatipamula wants to merge 4 commits intofilbeam:mainfrom
Conversation
pyropy
left a comment
There was a problem hiding this comment.
Great start! 👏🏻
I believe we're missing two very important things:
- Deployment script that upgrade the old contract without deploying a new proxy
- State view contract (I'm not sure if this is needed with UUPS contract but I've seen that you have mentioned it in the docs).
It is very important to us NOT to lose on-chain state during upgrades as that could potentially cause loss for both FilBeam and storage providers.
| ); | ||
|
|
||
| //Step 3: Deploy ERC1967 proxy pointing to the implementation | ||
| ERC1967Proxy proxy = new ERC1967Proxy(address(implementation), initializeData); |
There was a problem hiding this comment.
It looks like this will always deploy a new proxy contract? Should there be a separate script or way to upgrade proxy to a new implementation?
There was a problem hiding this comment.
ah yes i think having a seperate script for this is nice, so i'll set it to take proxy address as an environment variable, deploy new impl and call upgradeToAndCall on the proxy
src/FilBeamOperator.sol
Outdated
| uint256 public cdnRatePerByte; | ||
| uint256 public cacheMissRatePerByte; |
There was a problem hiding this comment.
| uint256 public cdnRatePerByte; | |
| uint256 public cacheMissRatePerByte; | |
| uint256 public immutable cdnRatePerByte; | |
| uint256 public immutable cacheMissRatePerByte; |
One of the decisions we have made during this contract development is to leave the rates immutable. Why is that you may wonder? It's because the way of how we actually report the usage.
So you see, we may change the rate from current $7 to $8, but there is no way for us to know if the reported egress usage happened before or after the price change. Therefore it would be unfair to charge users a new rate for egress usage that happened under the old rate.
If the rate change happens we'd have to deploy a new set of contracts, but upgradability is there to ensure that we can issue bugfixes without copying the state between smart contracts.
There was a problem hiding this comment.
ah now i get it, i was wondering why they were immutable. Thanks for letting me know-this makes total sense, this ensures fair billing without any ambiguity on which rate applies to the reported usage
src/FilBeamOperator.sol
Outdated
| address public fwssContractAddress; | ||
| address public fwssStateViewContractAddress; | ||
| address public paymentsContractAddress; |
There was a problem hiding this comment.
| address public fwssContractAddress; | |
| address public fwssStateViewContractAddress; | |
| address public paymentsContractAddress; | |
| address public immutable fwssContractAddress; | |
| address public immutable fwssStateViewContractAddress; | |
| address public immutable paymentsContractAddress; |
Since these are set during the initialization, I believe they may remain immutable. FWSS contract is doing a similar thing
There was a problem hiding this comment.
got it made them immutable and updated the scripts
DEPLOYMENT.md
Outdated
| cast call $FILBEAM_OPERATOR_ADDRESS "cdnRatePerByte()" --rpc-url $RPC_URL | ||
| cast call $FILBEAM_OPERATOR_ADDRESS "cacheMissRatePerByte()" --rpc-url $RPC_URL | ||
| cast call $FILBEAM_OPERATOR_ADDRESS "filBeamOperatorController()" --rpc-url $RPC_URL | ||
| cast call $FILBEAM_OPERATOR_ADDRESS "version()" --rpc-url $RPC_URL # Should return "1.0.0" |
There was a problem hiding this comment.
| cast call $FILBEAM_OPERATOR_ADDRESS "version()" --rpc-url $RPC_URL # Should return "1.0.0" | |
| cast call $FILBEAM_OPERATOR_PROXY_ADDRESS "version()" --rpc-url $RPC_URL # Should return "1.0.0" |
Let's perhaps make the exported variable more explicit.
DEPLOYMENT.md
Outdated
|
|
||
| ```bash | ||
| # Owner calls upgradeToAndCall on the proxy | ||
| cast send $FILBEAM_OPERATOR_ADDRESS \ |
There was a problem hiding this comment.
| cast send $FILBEAM_OPERATOR_ADDRESS \ | |
| cast send $FILBEAM_OPERATOR_PROXY_ADDRESS \ |
DEPLOYMENT.md
Outdated
| --rpc-url $RPC_URL \ | ||
| --private-key $OWNER_PRIVATE_KEY | ||
|
|
||
| export NEW_IMPLEMENTATION=0x... # New implementation address |
There was a problem hiding this comment.
| export NEW_IMPLEMENTATION=0x... # New implementation address | |
| export FILBEAM_OPERATOR_IMPL_ADDRESS=0x... # New implementation address |
DEPLOYMENT.md
Outdated
|
|
||
| ```bash | ||
| # Check new version | ||
| cast call $FILBEAM_OPERATOR_ADDRESS "version()" --rpc-url $RPC_URL |
There was a problem hiding this comment.
| cast call $FILBEAM_OPERATOR_ADDRESS "version()" --rpc-url $RPC_URL | |
| cast call $FILBEAM_OPERATOR_PROXY_ADDRESS "version()" --rpc-url $RPC_URL |
DEPLOYMENT.md
Outdated
| # Should return new version (e.g., "1.1.0") | ||
|
|
||
| # Verify state is preserved | ||
| cast call $FILBEAM_OPERATOR_ADDRESS "cdnRatePerByte()" --rpc-url $RPC_URL |
There was a problem hiding this comment.
| cast call $FILBEAM_OPERATOR_ADDRESS "cdnRatePerByte()" --rpc-url $RPC_URL | |
| cast call $FILBEAM_OPERATOR_PROXY_ADDRESS "cdnRatePerByte()" --rpc-url $RPC_URL |
README.md
Outdated
| uint256 _cdnRatePerByte, // Rate per byte for CDN usage | ||
| uint256 _cacheMissRatePerByte, // Rate per byte for cache-miss usage | ||
| address _filBeamOperatorController // Address authorized to report usage | ||
| address fwssStateViewAddress, // FWSS State View contract address |
There was a problem hiding this comment.
We're missing a state view contract 👀
There was a problem hiding this comment.
The state view contract is already integrated in FilBeamOperator.sol as fwssStateViewContractAddress it is used in _settlePaymentRail to actually query rail IDs, i just documented this existing parameter.
There was a problem hiding this comment.
Oh, great catch! For a moment I thought it was a FilBeamStateViewContract.
There was a problem hiding this comment.
yes as you said i dont think we may need a seperate FilBeamOperatorStateView contract since all the states are accessible via the public getters
…ntation improvements
7704faf to
d7434fc
Compare
pyropy
left a comment
There was a problem hiding this comment.
Great work! Let's upgrade the documentation before proceeding to merge this.
src/FilBeamOperator.sol
Outdated
| import "./Errors.sol"; | ||
| import {Ownable, Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol"; | ||
| import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; | ||
| import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; |
There was a problem hiding this comment.
| import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; |
Please remove this import as it's replaced by Ownable2StepUpgradeable
README.md
Outdated
| uint256 cacheMissRatePerByte, // Rate per byte for cache-miss usage | ||
| address filBeamOperatorController // Address authorized to report usage |
There was a problem hiding this comment.
| uint256 cacheMissRatePerByte, // Rate per byte for cache-miss usage | |
| address filBeamOperatorController // Address authorized to report usage | |
| uint256 cacheMissRatePerByte // Rate per byte for cache-miss usage |
filBeamOperatorController is removed from the initialize method.
There was a problem hiding this comment.
you mean filBeamOperatorController is the only thing kept in initialize method! the addresses and the rates were the ones moved to constructor to be immutable
| /// @param newImplementation Address of new implementation contract | ||
| function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} | ||
|
|
||
| function version() public pure virtual returns (string memory) { |
There was a problem hiding this comment.
The version() function returns a hardcoded "1.0.0" - consider documenting that this must be updated manually with each upgrade.
|
|
||
| ```bash | ||
| # Owner calls upgradeToAndCall on the proxy | ||
| cast send $FILBEAM_OPERATOR_PROXY_ADDRESS \ |
There was a problem hiding this comment.
The manual upgrade instructions using forge create are good for documentation, but consider referencing the new UpgradeFilBeamOperator.s.sol script as
the preferred method
script/UpgradeFilBeamOperator.s.sol
Outdated
|
|
||
| vm.stopBroadcast(); | ||
|
|
||
| // Step 2: Verify the upgrade |
There was a problem hiding this comment.
| // Step 2: Verify the upgrade | |
| // Step 3: Verify the upgrade |
|
@juliangruber would you also be able to give this a look? |
Description
This PR implements the UUPS (Universal Upgradeable Proxy Standard) proxy pattern for the FilBeamOperator contract, enabling safe contract upgrades while preserving all state.
Closes #3
Motivation
Key Implementation Details
Initializable,Ownable2StepUpgradeable,UUPSUpgradeableinitialize()replaces constructor (can only be called once)_disableInitializers()prevents implementation contract initialization_authorizeUpgrade()restricted to ownerversion()function returns"1.0.0"Testing
test_CannotInitializeTwicetest_CannotInitializeImplementationDirectlytest_OnlyOwnerCanUpgradetest_OwnerCanUpgradetest_VersionHow to Test
forge build forge test -vvv