Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make SFC and NodeDriver(Auth) upgradable #96

Merged
merged 9 commits into from
Nov 11, 2024
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
57 changes: 0 additions & 57 deletions contracts/common/Initializable.sol

This file was deleted.

96 changes: 0 additions & 96 deletions contracts/ownership/Ownable.sol

This file was deleted.

8 changes: 4 additions & 4 deletions contracts/sfc/ConstantsManager.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.27;

import {Ownable} from "../ownership/Ownable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {Decimal} from "../common/Decimal.sol";

/**
* @custom:security-contact security@fantom.foundation
*/
contract ConstantsManager is Ownable {
contract ConstantsManager is OwnableUpgradeable {
// Minimum amount of stake for a validator, i.e., 500000 FTM
uint256 public minSelfStake;
// Maximum ratio of delegations a validator can have, say, 15 times of self-stake
Expand Down Expand Up @@ -47,8 +47,8 @@ contract ConstantsManager is Ownable {
*/
error ValueTooLarge();

function initialize() external initializer {
Ownable.initialize(msg.sender);
constructor(address owner) initializer {
__Ownable_init(owner);
}

function updateMinSelfStake(uint256 v) external virtual onlyOwner {
Expand Down
8 changes: 4 additions & 4 deletions contracts/sfc/NetworkInitializer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
pragma solidity 0.8.27;

import {ISFC} from "../interfaces/ISFC.sol";
import {NodeDriver, NodeDriverAuth} from "./NodeDriver.sol";
import {NodeDriver} from "./NodeDriver.sol";
import {NodeDriverAuth} from "./NodeDriverAuth.sol";
import {ConstantsManager} from "./ConstantsManager.sol";
import {Decimal} from "../common/Decimal.sol";

Expand All @@ -20,11 +21,10 @@ contract NetworkInitializer {
address _evmWriter,
address _owner
) external {
NodeDriver(_driver).initialize(_auth, _evmWriter);
NodeDriver(_driver).initialize(_auth, _evmWriter, _owner);
NodeDriverAuth(_auth).initialize(_sfc, _driver, _owner);

ConstantsManager consts = new ConstantsManager();
consts.initialize();
ConstantsManager consts = new ConstantsManager(address(this));
consts.updateMinSelfStake(500000 * 1e18);
consts.updateMaxDelegatedRatio(16 * Decimal.unit());
consts.updateValidatorCommission((15 * Decimal.unit()) / 100);
Expand Down
22 changes: 10 additions & 12 deletions contracts/sfc/NodeDriver.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.27;

import {Initializable} from "../common/Initializable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {NodeDriverAuth} from "./NodeDriverAuth.sol";
import {IEVMWriter} from "../interfaces/IEVMWriter.sol";
import {INodeDriver} from "../interfaces/INodeDriver.sol";
Expand All @@ -12,21 +13,13 @@ import {INodeDriver} from "../interfaces/INodeDriver.sol";
* @dev Methods with onlyNode modifier are called by Sonic internal txs during epoch sealing.
* @custom:security-contact security@fantom.foundation
*/
contract NodeDriver is Initializable, INodeDriver {
contract NodeDriver is OwnableUpgradeable, UUPSUpgradeable, INodeDriver {
NodeDriverAuth internal backend;
IEVMWriter internal evmWriter;

error NotNode();
error NotBackend();

event UpdatedBackend(address indexed backend);

/// NodeDriverAuth can replace itself
function setBackend(address _backend) external onlyBackend {
emit UpdatedBackend(_backend);
backend = NodeDriverAuth(_backend);
}

/// Callable only by NodeDriverAuth (which mediates calls from SFC and from admins)
modifier onlyBackend() {
if (msg.sender != address(backend)) {
Expand All @@ -44,12 +37,17 @@ contract NodeDriver is Initializable, INodeDriver {

/// Initialization is called only once, after the contract deployment.
/// Because the contract code is written directly into genesis, constructor cannot be used.
function initialize(address _backend, address _evmWriterAddress) external initializer {
function initialize(address _backend, address _evmWriterAddress, address _owner) external initializer {
__Ownable_init(_owner);
__UUPSUpgradeable_init();
backend = NodeDriverAuth(_backend);
emit UpdatedBackend(_backend);
evmWriter = IEVMWriter(_evmWriterAddress);
}

/// Override the upgrade authorization check to allow upgrades only from the owner.
// solhint-disable-next-line no-empty-blocks
function _authorizeUpgrade(address) internal override onlyOwner {}

function setBalance(address acc, uint256 value) external onlyBackend {
evmWriter.setBalance(acc, value);
}
Expand Down
18 changes: 9 additions & 9 deletions contracts/sfc/NodeDriverAuth.sol
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.27;

import {Initializable} from "../common/Initializable.sol";
import {Ownable} from "../ownership/Ownable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {ISFC} from "../interfaces/ISFC.sol";
import {NodeDriver} from "./NodeDriver.sol";
import {INodeDriverExecutable} from "../interfaces/INodeDriverExecutable.sol";

/**
* @custom:security-contact security@fantom.foundation
*/
contract NodeDriverAuth is Initializable, Ownable {
contract NodeDriverAuth is OwnableUpgradeable, UUPSUpgradeable {
ISFC internal sfc;
NodeDriver internal driver;

Expand All @@ -23,11 +23,16 @@ contract NodeDriverAuth is Initializable, Ownable {

// Initialize NodeDriverAuth, NodeDriver and SFC in one call to allow fewer genesis transactions
function initialize(address payable _sfc, address _driver, address _owner) external initializer {
Ownable.initialize(_owner);
__Ownable_init(_owner);
__UUPSUpgradeable_init();
driver = NodeDriver(_driver);
sfc = ISFC(_sfc);
}

/// Override the upgrade authorization check to allow upgrades only from the owner.
// solhint-disable-next-line no-empty-blocks
function _authorizeUpgrade(address) internal override onlyOwner {}

/// Callable only by SFC contract.
modifier onlySFC() {
if (msg.sender != address(sfc)) {
Expand All @@ -44,11 +49,6 @@ contract NodeDriverAuth is Initializable, Ownable {
_;
}

/// Change NodeDriverAuth used by NodeDriver. Callable by network admin.
function migrateTo(address newDriverAuth) external onlyOwner {
driver.setBackend(newDriverAuth);
}

function _execute(address executable, address newOwner, bytes32 selfCodeHash, bytes32 driverCodeHash) internal {
_transferOwnership(executable);
INodeDriverExecutable(executable).execute();
Expand Down
13 changes: 9 additions & 4 deletions contracts/sfc/SFC.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.27;

import {Ownable} from "../ownership/Ownable.sol";
import {Initializable} from "../common/Initializable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {Decimal} from "../common/Decimal.sol";
import {NodeDriverAuth} from "./NodeDriverAuth.sol";
import {ConstantsManager} from "./ConstantsManager.sol";
Expand All @@ -13,7 +13,7 @@ import {Version} from "../version/Version.sol";
* @notice The SFC maintains a list of validators and delegators and distributes rewards to them.
* @custom:security-contact security@fantom.foundation
*/
contract SFC is Initializable, Ownable, Version {
contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version {
uint256 internal constant OK_STATUS = 0;
uint256 internal constant WITHDRAWN_BIT = 1;
uint256 internal constant OFFLINE_BIT = 1 << 3;
Expand Down Expand Up @@ -224,14 +224,19 @@ contract SFC is Initializable, Ownable, Version {
address _c,
address owner
) external initializer {
Ownable.initialize(owner);
__Ownable_init(owner);
__UUPSUpgradeable_init();
currentSealedEpoch = sealedEpoch;
node = NodeDriverAuth(nodeDriver);
c = ConstantsManager(_c);
totalSupply = _totalSupply;
getEpochSnapshot[sealedEpoch].endTime = _now();
}

/// Override the upgrade authorization check to allow upgrades only from the owner.
// solhint-disable-next-line no-empty-blocks
function _authorizeUpgrade(address) internal override onlyOwner {}

/// Receive fallback to revert transfers.
receive() external payable {
revert TransfersNotAllowed();
Expand Down
2 changes: 2 additions & 0 deletions contracts/test/UnitTestConstantsManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pragma solidity 0.8.27;
import {ConstantsManager} from "../sfc/ConstantsManager.sol";

contract UnitTestConstantsManager is ConstantsManager {
constructor(address owner) ConstantsManager(owner) {}

function updateMinSelfStake(uint256 v) external override onlyOwner {
minSelfStake = v;
}
Expand Down
5 changes: 2 additions & 3 deletions contracts/test/UnitTestSFC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,10 @@ contract UnitTestNetworkInitializer {
address _evmWriter,
address _owner
) external {
NodeDriver(_driver).initialize(_auth, _evmWriter);
NodeDriver(_driver).initialize(_auth, _evmWriter, _owner);
NodeDriverAuth(_auth).initialize(_sfc, _driver, _owner);

UnitTestConstantsManager consts = new UnitTestConstantsManager();
consts.initialize();
UnitTestConstantsManager consts = new UnitTestConstantsManager(address(this));
consts.updateMinSelfStake(0.3175000 * 1e18);
consts.updateMaxDelegatedRatio(16 * Decimal.unit());
consts.updateValidatorCommission((15 * Decimal.unit()) / 100);
Expand Down
3 changes: 2 additions & 1 deletion hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { HardhatUserConfig } from 'hardhat/config';
import * as dotenv from 'dotenv';
import '@nomicfoundation/hardhat-chai-matchers';
import '@nomicfoundation/hardhat-ethers';
import '@openzeppelin/hardhat-upgrades';
import '@typechain/hardhat';
import 'hardhat-contract-sizer';
import 'hardhat-gas-reporter';
import 'solidity-coverage';
import '@typechain/hardhat';

dotenv.config();

Expand Down
Loading