Skip to content

Commit

Permalink
feat(RewardsStreamerMP): make RewardsStreamerMP upgradeable
Browse files Browse the repository at this point in the history
This commit introduces upgradeability of the `RewardsStreamerMP`
contract by leveraging the UUPS pattern.

This means, for deployment, we have to first deploy an instance of
`RewardsStreamerMP` contract as a "template" logic contract and then
create a ERC1967Proxy that points to it.

The proxy ensures the implementation address is stored in a
deterministic storage slot.

This will later be leveraged by the `StakeVault` contract to implement
the functionality to leave the system in case there was a malicious
upgrade.

Closes #22
  • Loading branch information
3esmit authored and 0x-r4bbit committed Dec 1, 2024
1 parent e823711 commit 8561a68
Show file tree
Hide file tree
Showing 16 changed files with 341 additions and 193 deletions.
211 changes: 122 additions & 89 deletions .gas-report

Large diffs are not rendered by default.

170 changes: 86 additions & 84 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,84 +1,86 @@
EmergencyExitTest:test_CannotEnableEmergencyModeTwice() (gas: 79829)
EmergencyExitTest:test_CannotLeaveBeforeEmergencyMode() (gas: 283234)
EmergencyExitTest:test_EmergencyExitBasic() (gas: 379874)
EmergencyExitTest:test_EmergencyExitMultipleUsers() (gas: 788714)
EmergencyExitTest:test_EmergencyExitToAlternateAddress() (gas: 517455)
EmergencyExitTest:test_EmergencyExitWithLock() (gas: 370304)
EmergencyExitTest:test_EmergencyExitWithRewards() (gas: 507361)
EmergencyExitTest:test_OnlyOwnerCanEnableEmergencyMode() (gas: 34607)
IntegrationTest:testStakeFoo() (gas: 1490300)
LockTest:test_LockFailsWithInvalidPeriod() (gas: 290178)
LockTest:test_LockFailsWithNoStake() (gas: 53357)
LockTest:test_LockWithoutPriorLock() (gas: 383272)
NFTMetadataGeneratorSVGTest:testGenerateMetadata() (gas: 92874)
NFTMetadataGeneratorSVGTest:testSetImageStrings() (gas: 60081)
NFTMetadataGeneratorSVGTest:testSetImageStringsRevert() (gas: 35818)
NFTMetadataGeneratorURLTest:testGenerateMetadata() (gas: 109345)
NFTMetadataGeneratorURLTest:testSetBaseURL() (gas: 50653)
NFTMetadataGeneratorURLTest:testSetBaseURLRevert() (gas: 35993)
RewardsStreamerTest:testStake() (gas: 869874)
StakeTest:test_StakeMultipleAccounts() (gas: 493279)
StakeTest:test_StakeMultipleAccountsAndRewards() (gas: 640763)
StakeTest:test_StakeMultipleAccountsMPIncreasesMaxMPDoesNotChange() (gas: 818252)
StakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 499381)
StakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 520783)
StakeTest:test_StakeOneAccount() (gas: 284277)
StakeTest:test_StakeOneAccountAndRewards() (gas: 431756)
StakeTest:test_StakeOneAccountMPIncreasesMaxMPDoesNotChange() (gas: 498901)
StakeTest:test_StakeOneAccountReachingMPLimit() (gas: 494078)
StakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 298175)
StakeTest:test_StakeOneAccountWithMinLockUp() (gas: 298187)
StakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 298298)
StakingTokenTest:testStakeToken() (gas: 10426)
UnstakeTest:test_StakeMultipleAccounts() (gas: 493323)
UnstakeTest:test_StakeMultipleAccountsAndRewards() (gas: 640807)
UnstakeTest:test_StakeMultipleAccountsMPIncreasesMaxMPDoesNotChange() (gas: 818251)
UnstakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 499380)
UnstakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 520827)
UnstakeTest:test_StakeOneAccount() (gas: 284300)
UnstakeTest:test_StakeOneAccountAndRewards() (gas: 431800)
UnstakeTest:test_StakeOneAccountMPIncreasesMaxMPDoesNotChange() (gas: 498945)
UnstakeTest:test_StakeOneAccountReachingMPLimit() (gas: 494080)
UnstakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 298132)
UnstakeTest:test_StakeOneAccountWithMinLockUp() (gas: 298187)
UnstakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 298298)
UnstakeTest:test_UnstakeBonusMPAndAccuredMP() (gas: 508511)
UnstakeTest:test_UnstakeMultipleAccounts() (gas: 688755)
UnstakeTest:test_UnstakeMultipleAccountsAndRewards() (gas: 1014239)
UnstakeTest:test_UnstakeOneAccount() (gas: 480152)
UnstakeTest:test_UnstakeOneAccountAndAccruedMP() (gas: 496638)
UnstakeTest:test_UnstakeOneAccountAndRewards() (gas: 585964)
UnstakeTest:test_UnstakeOneAccountWithLockUpAndAccruedMP() (gas: 518574)
WithdrawTest:test_CannotWithdrawStakedFunds() (gas: 295608)
XPNFTTokenTest:testApproveNotAllowed() (gas: 10507)
XPNFTTokenTest:testGetApproved() (gas: 10531)
XPNFTTokenTest:testIsApprovedForAll() (gas: 10705)
XPNFTTokenTest:testSafeTransferNotAllowed() (gas: 10688)
XPNFTTokenTest:testSafeTransferWithDataNotAllowed() (gas: 10906)
XPNFTTokenTest:testSetApprovalForAllNotAllowed() (gas: 8474)
XPNFTTokenTest:testSetMetadataGenerator() (gas: 1014075)
XPNFTTokenTest:testSetMetadataGeneratorRevert() (gas: 1010606)
XPNFTTokenTest:testTokenURI() (gas: 111913)
XPNFTTokenTest:testTransferNotAllowed() (gas: 10723)
XPTokenMintAllowanceTest:testAddXPProviderOnlyOwner() (gas: 285721)
XPTokenMintAllowanceTest:testBalanceOf() (gas: 294561)
XPTokenMintAllowanceTest:testBalanceOfWithNoSystemTotalXP() (gas: 43428)
XPTokenMintAllowanceTest:testMintAllowance_Available() (gas: 205169)
XPTokenMintAllowanceTest:testMintAllowance_NotAvailable() (gas: 205107)
XPTokenMintAllowanceTest:testMintOnlyOwner() (gas: 241956)
XPTokenMintAllowanceTest:testMint_Ok() (gas: 264233)
XPTokenMintAllowanceTest:testMint_RevertWithAllowanceExceeded() (gas: 246656)
XPTokenMintAllowanceTest:testRemoveXPProviderIndexOutOfBounds() (gas: 36295)
XPTokenMintAllowanceTest:testRemoveXPProviderOnlyOwner() (gas: 72176)
XPTokenMintAllowanceTest:testTotalSupply() (gas: 202454)
XPTokenMintAllowanceTest:testTransfersNotAllowed() (gas: 20658)
XPTokenOwnershipTest:testInitialOwner() (gas: 12649)
XPTokenOwnershipTest:testOwnershipTransfer() (gas: 87271)
XPTokenTest:testAddXPProviderOnlyOwner() (gas: 285753)
XPTokenTest:testBalanceOf() (gas: 294565)
XPTokenTest:testBalanceOfWithNoSystemTotalXP() (gas: 43405)
XPTokenTest:testMintOnlyOwner() (gas: 241932)
XPTokenTest:testRemoveXPProviderIndexOutOfBounds() (gas: 36277)
XPTokenTest:testRemoveXPProviderOnlyOwner() (gas: 72141)
XPTokenTest:testTotalSupply() (gas: 202403)
XPTokenTest:testTransfersNotAllowed() (gas: 20702)
EmergencyExitTest:test_CannotEnableEmergencyModeTwice() (gas: 89646)
EmergencyExitTest:test_CannotLeaveBeforeEmergencyMode() (gas: 292881)
EmergencyExitTest:test_EmergencyExitBasic() (gas: 395173)
EmergencyExitTest:test_EmergencyExitMultipleUsers() (gas: 823179)
EmergencyExitTest:test_EmergencyExitToAlternateAddress() (gas: 538257)
EmergencyExitTest:test_EmergencyExitWithLock() (gas: 384549)
EmergencyExitTest:test_EmergencyExitWithRewards() (gas: 529680)
EmergencyExitTest:test_OnlyOwnerCanEnableEmergencyMode() (gas: 39344)
IntegrationTest:testStakeFoo() (gas: 1559037)
LockTest:test_LockFailsWithInvalidPeriod() (gas: 299830)
LockTest:test_LockFailsWithNoStake() (gas: 58241)
LockTest:test_LockWithoutPriorLock() (gas: 396542)
NFTMetadataGeneratorSVGTest:testGenerateMetadata() (gas: 85934)
NFTMetadataGeneratorSVGTest:testSetImageStrings() (gas: 58332)
NFTMetadataGeneratorSVGTest:testSetImageStringsRevert() (gas: 35804)
NFTMetadataGeneratorURLTest:testGenerateMetadata() (gas: 102512)
NFTMetadataGeneratorURLTest:testSetBaseURL() (gas: 49555)
NFTMetadataGeneratorURLTest:testSetBaseURLRevert() (gas: 35979)
RewardsStreamerTest:testStake() (gas: 869181)
StakeTest:test_StakeMultipleAccounts() (gas: 506030)
StakeTest:test_StakeMultipleAccountsAndRewards() (gas: 661839)
StakeTest:test_StakeMultipleAccountsMPIncreasesMaxMPDoesNotChange() (gas: 872090)
StakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 520069)
StakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 541881)
StakeTest:test_StakeOneAccount() (gas: 290297)
StakeTest:test_StakeOneAccountAndRewards() (gas: 446101)
StakeTest:test_StakeOneAccountMPIncreasesMaxMPDoesNotChange() (gas: 536165)
StakeTest:test_StakeOneAccountReachingMPLimit() (gas: 532401)
StakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 310643)
StakeTest:test_StakeOneAccountWithMinLockUp() (gas: 310610)
StakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 310721)
StakingTokenTest:testStakeToken() (gas: 10422)
UnstakeTest:test_StakeMultipleAccounts() (gas: 506074)
UnstakeTest:test_StakeMultipleAccountsAndRewards() (gas: 661883)
UnstakeTest:test_StakeMultipleAccountsMPIncreasesMaxMPDoesNotChange() (gas: 872089)
UnstakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 520068)
UnstakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 541925)
UnstakeTest:test_StakeOneAccount() (gas: 290320)
UnstakeTest:test_StakeOneAccountAndRewards() (gas: 446145)
UnstakeTest:test_StakeOneAccountMPIncreasesMaxMPDoesNotChange() (gas: 536209)
UnstakeTest:test_StakeOneAccountReachingMPLimit() (gas: 532403)
UnstakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 310600)
UnstakeTest:test_StakeOneAccountWithMinLockUp() (gas: 310610)
UnstakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 310721)
UnstakeTest:test_UnstakeBonusMPAndAccuredMP() (gas: 541859)
UnstakeTest:test_UnstakeMultipleAccounts() (gas: 714931)
UnstakeTest:test_UnstakeMultipleAccountsAndRewards() (gas: 1057383)
UnstakeTest:test_UnstakeOneAccount() (gas: 499845)
UnstakeTest:test_UnstakeOneAccountAndAccruedMP() (gas: 524183)
UnstakeTest:test_UnstakeOneAccountAndRewards() (gas: 608646)
UnstakeTest:test_UnstakeOneAccountWithLockUpAndAccruedMP() (gas: 555708)
UpgradeTest:test_RevertWhenNotOwner() (gas: 2159991)
UpgradeTest:test_UpgradeStakeManager() (gas: 2445373)
WithdrawTest:test_CannotWithdrawStakedFunds() (gas: 305631)
XPNFTTokenTest:testApproveNotAllowed() (gas: 10500)
XPNFTTokenTest:testGetApproved() (gas: 10523)
XPNFTTokenTest:testIsApprovedForAll() (gas: 10698)
XPNFTTokenTest:testSafeTransferNotAllowed() (gas: 10680)
XPNFTTokenTest:testSafeTransferWithDataNotAllowed() (gas: 10897)
XPNFTTokenTest:testSetApprovalForAllNotAllowed() (gas: 8467)
XPNFTTokenTest:testSetMetadataGenerator() (gas: 969770)
XPNFTTokenTest:testSetMetadataGeneratorRevert() (gas: 966301)
XPNFTTokenTest:testTokenURI() (gas: 103894)
XPNFTTokenTest:testTransferNotAllowed() (gas: 10715)
XPTokenMintAllowanceTest:testAddXPProviderOnlyOwner() (gas: 282868)
XPTokenMintAllowanceTest:testBalanceOf() (gas: 294494)
XPTokenMintAllowanceTest:testBalanceOfWithNoSystemTotalXP() (gas: 43385)
XPTokenMintAllowanceTest:testMintAllowance_Available() (gas: 205108)
XPTokenMintAllowanceTest:testMintAllowance_NotAvailable() (gas: 205044)
XPTokenMintAllowanceTest:testMintOnlyOwner() (gas: 241885)
XPTokenMintAllowanceTest:testMint_Ok() (gas: 264142)
XPTokenMintAllowanceTest:testMint_RevertWithAllowanceExceeded() (gas: 246592)
XPTokenMintAllowanceTest:testRemoveXPProviderIndexOutOfBounds() (gas: 36286)
XPTokenMintAllowanceTest:testRemoveXPProviderOnlyOwner() (gas: 72143)
XPTokenMintAllowanceTest:testTotalSupply() (gas: 202403)
XPTokenMintAllowanceTest:testTransfersNotAllowed() (gas: 20631)
XPTokenOwnershipTest:testInitialOwner() (gas: 12645)
XPTokenOwnershipTest:testOwnershipTransfer() (gas: 87252)
XPTokenTest:testAddXPProviderOnlyOwner() (gas: 282900)
XPTokenTest:testBalanceOf() (gas: 294498)
XPTokenTest:testBalanceOfWithNoSystemTotalXP() (gas: 43362)
XPTokenTest:testMintOnlyOwner() (gas: 241861)
XPTokenTest:testRemoveXPProviderIndexOutOfBounds() (gas: 36268)
XPTokenTest:testRemoveXPProviderOnlyOwner() (gas: 72108)
XPTokenTest:testTotalSupply() (gas: 202352)
XPTokenTest:testTransfersNotAllowed() (gas: 20675)
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ jobs:
run: "pnpm install"

- name: Verify rules
run: "pnpm verify"
run: |
pnpm ${{matrix.rule}}
env:
CERTORAKEY: ${{ secrets.CERTORAKEY }}

Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "lib/openzeppelin-contracts-upgradeable"]
path = lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
3 changes: 2 additions & 1 deletion certora/confs/EmergencyMode.conf
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"loop_iter": "3",
"packages": [
"forge-std=lib/forge-std/src",
"@openzeppelin=lib/openzeppelin-contracts"
"@openzeppelin=lib/openzeppelin-contracts",
"@openzeppelin/contracts-upgradeable=lib/openzeppelin-contracts-upgradeable/contracts"
]
}

3 changes: 2 additions & 1 deletion certora/confs/RewardsStreamerMP.conf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"loop_iter": "3",
"packages": [
"forge-std=lib/forge-std/src",
"@openzeppelin=lib/openzeppelin-contracts"
"@openzeppelin/contracts=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts",
"@openzeppelin/contracts-upgradeable=lib/openzeppelin-contracts-upgradeable/contracts"
]
}
15 changes: 14 additions & 1 deletion certora/specs/EmergencyMode.spec
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ definition isTrustedCodehashAccessFunction(method f) returns bool = (
f.selector == sig:streamer.isTrustedCodehash(bytes32).selector
);

definition isInitializerFunction(method f) returns bool = (
f.selector == sig:streamer.initialize(address,address,address).selector
);

definition isUUPSUpgradeableFunction(method f) returns bool = (
f.selector == sig:streamer.proxiableUUID().selector ||
f.selector == sig:streamer.UPGRADE_INTERFACE_VERSION().selector ||
f.selector == sig:streamer.upgradeToAndCall(address, bytes).selector ||
f.selector == sig:streamer.__TrustedCodehashAccess_init(address).selector
);

rule accountCanOnlyLeaveInEmergencyMode(method f) {
env e;
calldataarg args;
Expand All @@ -49,6 +60,8 @@ rule accountCanOnlyLeaveInEmergencyMode(method f) {

assert !isReverted => isViewFunction(f) ||
isOwnableFunction(f) ||
isTrustedCodehashAccessFunction(f);
isTrustedCodehashAccessFunction(f) ||
isInitializerFunction(f) ||
isUUPSUpgradeableFunction(f);
}

15 changes: 12 additions & 3 deletions certora/specs/RewardsStreamerMP.spec
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,22 @@ function getAccountLockUntil(address account) returns uint256 {
}

invariant sumOfBalancesIsTotalStaked()
sumOfBalances == to_mathint(totalStaked());
sumOfBalances == to_mathint(totalStaked())
filtered {
f -> f.selector != sig:upgradeToAndCall(address,bytes).selector
}

invariant accountMPLessEqualAccountMaxMP(address account)
to_mathint(getAccountMP(account)) <= to_mathint(getAccountMaxMP(account));
to_mathint(getAccountMP(account)) <= to_mathint(getAccountMaxMP(account))
filtered {
f -> f.selector != sig:upgradeToAndCall(address,bytes).selector
}

invariant accountMPGreaterEqualAccountStakedBalance(address account)
to_mathint(getAccountMP(account)) >= to_mathint(getAccountStakedBalance(account));
to_mathint(getAccountMP(account)) >= to_mathint(getAccountStakedBalance(account))
filtered {
f -> f.selector != sig:upgradeToAndCall(address,bytes).selector
}

rule stakingMintsMultiplierPoints1To1Ratio {

Expand Down
3 changes: 1 addition & 2 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
block_timestamp = 1_680_220_800 # March 31, 2023 at 00:00 GMT
bytecode_hash = "none"
cbor_metadata = false
evm_version = "paris"
evm_version = "cancun"
fuzz = { runs = 1_000 }
gas_reports = ["*"]
libs = ["lib"]
Expand All @@ -16,7 +16,6 @@
solc = "0.8.26"
src = "src"
test = "test"

[profile.ci]
fuzz = { runs = 10_000 }
verbosity = 4
Expand Down
1 change: 1 addition & 0 deletions lib/openzeppelin-contracts-upgradeable
3 changes: 2 additions & 1 deletion remappings.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
forge-std/=lib/forge-std/src/
@openzeppelin/contracts=./lib/openzeppelin-contracts/contracts
@openzeppelin/contracts=lib/openzeppelin-contracts/contracts
@openzeppelin/contracts-upgradeable=lib/openzeppelin-contracts-upgradeable/contracts
1 change: 1 addition & 0 deletions slither.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"detectors_to_exclude": "naming-convention,reentrancy-events,solc-version,timestamp",
"filter_paths": "(lib|test)",
"solc_remaps": [
"@openzeppelin/contracts-upgradeable=lib/openzeppelin-contracts-upgradeable/contracts",
"@openzeppelin/contracts=lib/openzeppelin-contracts/contracts/",
"forge-std/=lib/forge-std/src/"
]
Expand Down
24 changes: 19 additions & 5 deletions src/RewardsStreamerMP.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
pragma solidity ^0.8.26;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

Check warning on line 6 in src/RewardsStreamerMP.sol

View workflow job for this annotation

GitHub Actions / lint

imported name Initializable is not used
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import { IStakeManager } from "./interfaces/IStakeManager.sol";
import { TrustedCodehashAccess } from "./TrustedCodehashAccess.sol";

// Rewards Streamer with Multiplier Points
contract RewardsStreamerMP is IStakeManager, TrustedCodehashAccess, ReentrancyGuard {
contract RewardsStreamerMP is UUPSUpgradeable, IStakeManager, TrustedCodehashAccess, ReentrancyGuardUpgradeable {
error StakingManager__AmountCannotBeZero();
error StakingManager__TransferFailed();
error StakingManager__InsufficientBalance();
Expand All @@ -17,8 +19,8 @@ contract RewardsStreamerMP is IStakeManager, TrustedCodehashAccess, ReentrancyGu
error StakingManager__AlreadyLocked();
error StakingManager__EmergencyModeEnabled();

IERC20 public immutable STAKING_TOKEN;
IERC20 public immutable REWARD_TOKEN;
IERC20 public STAKING_TOKEN;

Check warning on line 22 in src/RewardsStreamerMP.sol

View workflow job for this annotation

GitHub Actions / lint

Variable name must be in mixedCase
IERC20 public REWARD_TOKEN;

Check warning on line 23 in src/RewardsStreamerMP.sol

View workflow job for this annotation

GitHub Actions / lint

Variable name must be in mixedCase

uint256 public constant SCALE_FACTOR = 1e18;
uint256 public constant MP_RATE_PER_YEAR = 1e18;
Expand Down Expand Up @@ -53,12 +55,24 @@ contract RewardsStreamerMP is IStakeManager, TrustedCodehashAccess, ReentrancyGu
_;
}

constructor(address _owner, address _stakingToken, address _rewardToken) TrustedCodehashAccess(_owner) {
constructor() {
_disableInitializers();
}

function initialize(address _owner, address _stakingToken, address _rewardToken) public initializer {
__TrustedCodehashAccess_init(_owner);
__UUPSUpgradeable_init();
__ReentrancyGuard_init();

STAKING_TOKEN = IERC20(_stakingToken);
REWARD_TOKEN = IERC20(_rewardToken);
lastMPUpdatedTime = block.timestamp;
}

function _authorizeUpgrade(address) internal view override {
_checkOwner();
}

function stake(uint256 amount, uint256 lockPeriod) external onlyTrustedCodehash onlyNotEmergencyMode nonReentrant {
if (amount == 0) {
revert StakingManager__AmountCannotBeZero();
Expand Down
8 changes: 5 additions & 3 deletions src/TrustedCodehashAccess.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { ITrustedCodehashAccess } from "./interfaces/ITrustedCodehashAccess.sol";
/**
* @title TrustedCodehashAccess
Expand All @@ -10,7 +10,7 @@ import { ITrustedCodehashAccess } from "./interfaces/ITrustedCodehashAccess.sol"
* interact with the functions using the `onlyTrustedCodehash` modifier.
*/

contract TrustedCodehashAccess is ITrustedCodehashAccess, Ownable {
abstract contract TrustedCodehashAccess is ITrustedCodehashAccess, OwnableUpgradeable {
mapping(bytes32 codehash => bool permission) private trustedCodehashes;

/**
Expand All @@ -25,7 +25,9 @@ contract TrustedCodehashAccess is ITrustedCodehashAccess, Ownable {
_;
}

constructor(address _owner) Ownable(_owner) { }
function __TrustedCodehashAccess_init(address _initialOwner) public onlyInitializing {
__Ownable_init(_initialOwner);
}

/**
* @notice Allows the owner to set or update the trust status for a contract's codehash.
Expand Down
Loading

0 comments on commit 8561a68

Please sign in to comment.