diff --git a/contracts/interfaces/ISFC.sol b/contracts/interfaces/ISFC.sol index 5e48c31..10813c7 100644 --- a/contracts/interfaces/ISFC.sol +++ b/contracts/interfaces/ISFC.sol @@ -127,6 +127,8 @@ interface ISFC { function getEpochEndBlock(uint256 epoch) external view returns (uint256); + function epochEndTime(uint256 epoch) external view returns (uint256); + function rewardsStash(address delegator, uint256 validatorID) external view returns (uint256); function createValidator(bytes calldata pubkey) external payable; diff --git a/contracts/sfc/SFC.sol b/contracts/sfc/SFC.sol index dde09c6..ff112c6 100644 --- a/contracts/sfc/SFC.sol +++ b/contracts/sfc/SFC.sol @@ -225,7 +225,7 @@ contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version { event TreasuryFeesResolved(uint256 amount); modifier onlyDriver() { - if (!isNode(msg.sender)) { + if (!_isNode(msg.sender)) { revert NotDriverAuth(); } _; @@ -606,6 +606,11 @@ contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version { return getEpochSnapshot[epoch].endBlock; } + /// Get epoch end time. + function epochEndTime(uint256 epoch) public view returns (uint256) { + return getEpochSnapshot[epoch].endTime; + } + /// Check whether the given validator is slashed - the stake (or its part) cannot /// be withdrawn because of misbehavior (double-sign) of the validator. function isSlashed(uint256 validatorID) public view returns (bool) { @@ -626,7 +631,7 @@ contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version { } /// Check if an address is the NodeDriverAuth contract. - function isNode(address addr) internal view virtual returns (bool) { + function _isNode(address addr) internal view virtual returns (bool) { return addr == address(node); } @@ -703,7 +708,7 @@ contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version { } /// Get slashing penalty for a stake. - function getSlashingPenalty( + function _getSlashingPenalty( uint256 amount, bool isCheater, uint256 refundRatio @@ -747,7 +752,7 @@ contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version { uint256 amount = getWithdrawalRequest[delegator][toValidatorID][wrID].amount; bool isCheater = isSlashed(toValidatorID); - uint256 penalty = getSlashingPenalty(amount, isCheater, slashingRefundRatio[toValidatorID]); + uint256 penalty = _getSlashingPenalty(amount, isCheater, slashingRefundRatio[toValidatorID]); delete getWithdrawalRequest[delegator][toValidatorID][wrID]; if (amount <= penalty) { @@ -835,11 +840,6 @@ contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version { } } - /// Get epoch end time. - function epochEndTime(uint256 epoch) internal view returns (uint256) { - return getEpochSnapshot[epoch].endTime; - } - /// Check if an address is redirected. function _redirected(address addr) internal view returns (bool) { return getRedirection[addr] != address(0); @@ -1107,6 +1107,22 @@ contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version { totalSupply = totalSupply + amount; } + /// Sync validator with node. + function _syncValidator(uint256 validatorID, bool syncPubkey) internal { + if (!_validatorExists(validatorID)) { + revert ValidatorNotExists(); + } + // emit special log for node + uint256 weight = getValidator[validatorID].receivedStake; + if (getValidator[validatorID].status != OK_STATUS) { + weight = 0; + } + node.updateValidatorWeight(validatorID, weight); + if (syncPubkey && weight != 0) { + node.updateValidatorPubkey(validatorID, getValidatorPubkey[validatorID]); + } + } + /// Notify stake subscriber about staking changes. /// Used to recount votes from delegators in the governance contract. function _notifyStakeSubscriber(address delegator, address validatorAuth, bool strict) internal { @@ -1144,22 +1160,6 @@ contract SFC is OwnableUpgradeable, UUPSUpgradeable, Version { } } - /// Sync validator with node. - function _syncValidator(uint256 validatorID, bool syncPubkey) public { - if (!_validatorExists(validatorID)) { - revert ValidatorNotExists(); - } - // emit special log for node - uint256 weight = getValidator[validatorID].receivedStake; - if (getValidator[validatorID].status != OK_STATUS) { - weight = 0; - } - node.updateValidatorWeight(validatorID, weight); - if (syncPubkey && weight != 0) { - node.updateValidatorPubkey(validatorID, getValidatorPubkey[validatorID]); - } - } - /// Check if a validator exists. function _validatorExists(uint256 validatorID) internal view returns (bool) { return getValidator[validatorID].createdTime != 0; diff --git a/contracts/test/UnitTestSFC.sol b/contracts/test/UnitTestSFC.sol index e45a54d..5c40c05 100644 --- a/contracts/test/UnitTestSFC.sol +++ b/contracts/test/UnitTestSFC.sol @@ -40,11 +40,15 @@ contract UnitTestSFC is SFC { return time; } - function isNode(address addr) internal view override returns (bool) { + function _isNode(address addr) internal view override returns (bool) { if (allowedNonNodeCalls) { return true; } - return SFC.isNode(addr); + return SFC._isNode(addr); + } + + function syncValidator(uint256 validatorID, bool syncPubkey) public { + _syncValidator(validatorID, syncPubkey); } } diff --git a/test/SFC.ts b/test/SFC.ts index 0b7ea7e..a7fbe77 100644 --- a/test/SFC.ts +++ b/test/SFC.ts @@ -93,7 +93,7 @@ describe('SFC', () => { }); it('Should succeed and set genesis validator with bad status', async function () { - await this.sfc._syncValidator(1, false); + await this.sfc.syncValidator(1, false); }); it('Should revert when sealEpoch not called by node', async function () { @@ -1056,7 +1056,7 @@ describe('SFC', () => { }); it('Should revert when syncing if validator does not exist', async function () { - await expect(this.sfc._syncValidator(33, false)).to.be.revertedWithCustomError(this.sfc, 'ValidatorNotExists'); + await expect(this.sfc.syncValidator(33, false)).to.be.revertedWithCustomError(this.sfc, 'ValidatorNotExists'); }); });