Skip to content

Commit

Permalink
feat: deprecate transferOut in TokenHub
Browse files Browse the repository at this point in the history
  • Loading branch information
pythonberg1997 committed Jan 15, 2024
1 parent 8e5e491 commit 2371798
Show file tree
Hide file tree
Showing 6 changed files with 349 additions and 347 deletions.
2 changes: 1 addition & 1 deletion abi/bscvalidatorset.abi
Original file line number Diff line number Diff line change
Expand Up @@ -843,7 +843,7 @@
"name": "getCurrentValidatorIndex",
"inputs": [
{
"name": "_validator",
"name": "validator",
"type": "address",
"internalType": "address"
}
Expand Down
22 changes: 22 additions & 0 deletions contracts/BC_fusion/StakeHub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,9 @@ contract StakeHub is System, Initializable {
}

/**
* @param operatorAddress the operator address of the validator
* @param index the index of the day to query(timestamp / 1 days)
*
* @return the validator's reward of the day
*/
function getValidatorRewardRecord(address operatorAddress, uint256 index) external view returns (uint256) {
Expand All @@ -868,6 +871,9 @@ contract StakeHub is System, Initializable {
}

/**
* @param operatorAddress the operator address of the validator
* @param index the index of the day to query(timestamp / 1 days)
*
* @return the validator's total pooled BNB of the day
*/
function getValidatorTotalPooledBNBRecord(address operatorAddress, uint256 index) external view returns (uint256) {
Expand All @@ -877,6 +883,10 @@ contract StakeHub is System, Initializable {

/**
* @notice pagination query all validators' operator address and credit contract address
*
* @param offset the offset of the query
* @param limit the limit of the query
*
* @return operatorAddrs operator addresses
* @return creditAddrs credit contract addresses
* @return totalLength total number of validators
Expand All @@ -902,6 +912,9 @@ contract StakeHub is System, Initializable {

/**
* @notice get the basic info of a validator
*
* @param operatorAddress the operator address of the validator
*
* @return consensusAddress the consensus address of the validator
* @return creditContract the credit contract address of the validator
* @return createdTime the creation time of the validator
Expand Down Expand Up @@ -932,6 +945,8 @@ contract StakeHub is System, Initializable {
}

/**
* @param operatorAddress the operator address of the validator
*
* @return the description of a validator
*/
function getValidatorDescription(address operatorAddress)
Expand All @@ -944,6 +959,8 @@ contract StakeHub is System, Initializable {
}

/**
* @param operatorAddress the operator address of the validator
*
* @return the commission of a validator
*/
function getValidatorCommission(address operatorAddress)
Expand All @@ -957,7 +974,12 @@ contract StakeHub is System, Initializable {

/**
* @dev this function will be used by Parlia consensus engine.
*
* @notice get the election info of a validator
*
* @param offset the offset of the query
* @param limit the limit of the query
*
* @return consensusAddrs the consensus addresses of the validators
* @return votingPowers the voting powers of the validators. The voting power will be 0 if the validator is jailed.
* @return voteAddrs the vote addresses of the validators
Expand Down
238 changes: 128 additions & 110 deletions contracts/BSCValidatorSet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,6 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica

/**
* @dev With each epoch, there will be a partial rotation between cabinets and candidates. Rotation is determined by this function
*
*/
function shuffle(address[] memory validators, bytes[] memory voteAddrs, uint256 epochNumber, uint startIdx, uint offset, uint limit, uint modNumber) internal pure {
for (uint i; i<limit; ++i) {
Expand All @@ -548,6 +547,81 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica
}
}

function distributeFinalityReward(address[] calldata valAddrs, uint256[] calldata weights) external onlyCoinbase oncePerBlock onlyZeroGasPrice onlyInit {
uint256 totalValue;
uint256 balanceOfSystemReward = address(SYSTEM_REWARD_ADDR).balance;
if (balanceOfSystemReward > MAX_SYSTEM_REWARD_BALANCE) {
// when a slash happens, theres will no rewards in some epochs,
// it's tolerated because slash happens rarely
totalValue = balanceOfSystemReward.sub(MAX_SYSTEM_REWARD_BALANCE);
} else {
return;
}

totalValue = ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(payable(address(this)), totalValue);
if (totalValue == 0) {
return;
}

uint256 totalWeight;
for (uint256 i; i<weights.length; ++i) {
totalWeight += weights[i];
}
if (totalWeight == 0) {
return;
}

uint256 value;
address valAddr;
uint256 index;

for (uint256 i; i<valAddrs.length; ++i) {
value = (totalValue * weights[i]) / totalWeight;
valAddr = valAddrs[i];
index = currentValidatorSetMap[valAddr];
if (index > 0) {
Validator storage validator = currentValidatorSet[index - 1];
if (validator.jailed) {
emit deprecatedFinalityRewardDeposit(valAddr, value);
} else {
totalInComing = totalInComing.add(value);
validator.incoming = validator.incoming.add(value);
emit finalityRewardDeposit(valAddr, value);
}
} else {
// get incoming from deprecated validator;
emit deprecatedFinalityRewardDeposit(valAddr, value);
}
}

}

/*********************** View Functions **************************/
/**
* @notice Return the consensus address of the validators in `currentValidatorSet` that are not jailed and not maintaining
*/
function getValidators() public view returns(address[] memory) {
uint n = currentValidatorSet.length;
uint valid = 0;
for (uint i; i<n; ++i) {
if (isWorkingValidator(i)) {
++valid;
}
}
address[] memory consensusAddrs = new address[](valid);
valid = 0;
for (uint i; i<n; ++i) {
if (isWorkingValidator(i)) {
consensusAddrs[valid] = currentValidatorSet[i].consensusAddress;
++valid;
}
}
return consensusAddrs;
}

/**
* @notice Return the vote address and consensus address of the validators in `currentValidatorSet` that are not jailed
*/
function getLivingValidators() external view override returns (address[] memory, bytes[] memory) {
uint n = currentValidatorSet.length;
uint living;
Expand Down Expand Up @@ -579,14 +653,14 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica
}

/**
* @dev Get mining validators that are block producers in the current epoch, including most of the cabinets and a few of the candidates
* @notice Return the vote address and consensus address of mining validators
*
* Mining validators are block producers in the current epoch
* including most of the cabinets and a few of the candidates
*/
function getMiningValidators() external view override returns(address[] memory, bytes[] memory) {
uint256 _maxNumOfWorkingCandidates = maxNumOfWorkingCandidates;
uint256 _numOfCabinets = numOfCabinets;
if (_numOfCabinets == 0 ){
_numOfCabinets = INIT_NUM_OF_CABINETS;
}
uint256 _numOfCabinets = numOfCabinets > 0 ? numOfCabinets : INIT_NUM_OF_CABINETS;

address[] memory validators = getValidators();
bytes[] memory voteAddrs = getVoteAddresses(validators);
Expand All @@ -613,28 +687,10 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica
}

/**
* @dev Get all validators, including all of the cabinets and all of the candidates
* @notice Return whether the validator is a working validator(not jailed or maintaining) by index
*
* @param index The index of the validator in `currentValidatorSet`(from 0 to `currentValidatorSet.length-1`)
*/
function getValidators() public view returns(address[] memory) {
uint n = currentValidatorSet.length;
uint valid = 0;
for (uint i; i<n; ++i) {
if (isWorkingValidator(i)) {
++valid;
}
}
address[] memory consensusAddrs = new address[](valid);
valid = 0;
for (uint i; i<n; ++i) {
if (isWorkingValidator(i)) {
consensusAddrs[valid] = currentValidatorSet[i].consensusAddress;
++valid;
}
}
return consensusAddrs;
}

function isWorkingValidator(uint index) public view returns (bool) {
if (index >= currentValidatorSet.length) {
return false;
Expand All @@ -648,14 +704,10 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica
return !currentValidatorSet[index].jailed && !validatorExtraSet[index].isMaintaining;
}

function getIncoming(address validator)external view returns(uint256) {
uint256 index = currentValidatorSetMap[validator];
if (index<=0) {
return 0;
}
return currentValidatorSet[index-1].incoming;
}

/**
* @notice Return whether the validator is a working validator(not jailed or maintaining) by consensus address
* Will return false if the validator is not in `currentValidatorSet`
*/
function isCurrentValidator(address validator) external view override returns (bool) {
uint256 index = currentValidatorSetMap[validator];
if (index <= 0) {
Expand All @@ -667,53 +719,15 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica
return isWorkingValidator(index);
}

function distributeFinalityReward(address[] calldata valAddrs, uint256[] calldata weights) external onlyCoinbase oncePerBlock onlyZeroGasPrice onlyInit {
uint256 totalValue;
uint256 balanceOfSystemReward = address(SYSTEM_REWARD_ADDR).balance;
if (balanceOfSystemReward > MAX_SYSTEM_REWARD_BALANCE) {
// when a slash happens, theres will no rewards in some epochs,
// it's tolerated because slash happens rarely
totalValue = balanceOfSystemReward.sub(MAX_SYSTEM_REWARD_BALANCE);
} else {
return;
}

totalValue = ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(payable(address(this)), totalValue);
if (totalValue == 0) {
return;
}

uint256 totalWeight;
for (uint256 i; i<weights.length; ++i) {
totalWeight += weights[i];
}
if (totalWeight == 0) {
return;
}

uint256 value;
address valAddr;
uint256 index;

for (uint256 i; i<valAddrs.length; ++i) {
value = (totalValue * weights[i]) / totalWeight;
valAddr = valAddrs[i];
index = currentValidatorSetMap[valAddr];
if (index > 0) {
Validator storage validator = currentValidatorSet[index - 1];
if (validator.jailed) {
emit deprecatedFinalityRewardDeposit(valAddr, value);
} else {
totalInComing = totalInComing.add(value);
validator.incoming = validator.incoming.add(value);
emit finalityRewardDeposit(valAddr, value);
}
} else {
// get incoming from deprecated validator;
emit deprecatedFinalityRewardDeposit(valAddr, value);
}
/**
* @notice Return the current incoming of the validator
*/
function getIncoming(address validator)external view returns(uint256) {
uint256 index = currentValidatorSetMap[validator];
if (index<=0) {
return 0;
}

return currentValidatorSet[index-1].incoming;
}

function getWorkingValidatorCount() public view returns(uint256 workingValidatorCount) {
Expand All @@ -727,6 +741,40 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica
}
}

/**
* @notice Return the index of the validator in `currentValidatorSet`(from 0 to `currentValidatorSet.length-1`)
*/
function getCurrentValidatorIndex(address validator) public view returns (uint256) {
uint256 index = currentValidatorSetMap[validator];
require(index > 0, "only current validators");

// the actual index
return index - 1;
}

/**
* @notice Return whether the validator at index could enter maintenance
*/
function canEnterMaintenance(uint256 index) public view returns (bool) {
if (index >= currentValidatorSet.length) {
return false;
}

if (
currentValidatorSet[index].consensusAddress == address(0) // - 0. check if empty validator
|| (maxNumOfMaintaining == 0 || maintainSlashScale == 0) // - 1. check if not start
|| numOfMaintaining >= maxNumOfMaintaining // - 2. check if reached upper limit
|| !isWorkingValidator(index) // - 3. check if not working(not jailed and not maintaining)
|| validatorExtraSet[index].enterMaintenanceHeight > 0 // - 5. check if has Maintained during current 24-hour period
// current validators are selected every 24 hours(from 00:00:00 UTC to 23:59:59 UTC)
|| getValidators().length <= 1 // - 6. check num of remaining working validators
) {
return false;
}

return true;
}

/*********************** For slash **************************/
function misdemeanor(address validator) external onlySlash initValidatorExtraSet override {
uint256 validatorIndex = _misdemeanor(validator);
Expand Down Expand Up @@ -761,37 +809,8 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica
}

/*********************** For Temporary Maintenance **************************/
function getCurrentValidatorIndex(address _validator) public view returns (uint256) {
uint256 index = currentValidatorSetMap[_validator];
require(index > 0, "only current validators");

// the actual index
return index - 1;
}

function canEnterMaintenance(uint256 index) public view returns (bool) {
if (index >= currentValidatorSet.length) {
return false;
}

if (
currentValidatorSet[index].consensusAddress == address(0) // - 0. check if empty validator
|| (maxNumOfMaintaining == 0 || maintainSlashScale == 0) // - 1. check if not start
|| numOfMaintaining >= maxNumOfMaintaining // - 2. check if reached upper limit
|| !isWorkingValidator(index) // - 3. check if not working(not jailed and not maintaining)
|| validatorExtraSet[index].enterMaintenanceHeight > 0 // - 5. check if has Maintained during current 24-hour period
// current validators are selected every 24 hours(from 00:00:00 UTC to 23:59:59 UTC)
|| getValidators().length <= 1 // - 6. check num of remaining working validators
) {
return false;
}

return true;
}

/**
* @dev Enter maintenance for current validators. refer to https://github.com/bnb-chain/BEPs/blob/master/BEP127.md
*
*/
function enterMaintenance() external initValidatorExtraSet {
// check maintain config
Expand All @@ -809,7 +828,6 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica

/**
* @dev Exit maintenance for current validators. refer to https://github.com/bnb-chain/BEPs/blob/master/BEP127.md
*
*/
function exitMaintenance() external {
uint256 index = getCurrentValidatorIndex(msg.sender);
Expand Down
Loading

0 comments on commit 2371798

Please sign in to comment.