diff --git a/abi/bscvalidatorset.abi b/abi/bscvalidatorset.abi index 9c9c265e6..1f1ece863 100644 --- a/abi/bscvalidatorset.abi +++ b/abi/bscvalidatorset.abi @@ -627,6 +627,19 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "antiMEVSystemRewardRatio", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "bscChainID", @@ -912,6 +925,19 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getTurnTerm", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "getValidators", @@ -1005,6 +1031,19 @@ "outputs": [], "stateMutability": "nonpayable" }, + { + "type": "function", + "name": "initSystemRewardRatio", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "isCurrentValidator", @@ -1239,7 +1278,7 @@ }, { "type": "function", - "name": "systemRewardRatio", + "name": "totalInComing", "inputs": [], "outputs": [ { @@ -1252,7 +1291,7 @@ }, { "type": "function", - "name": "totalInComing", + "name": "turnTerm", "inputs": [], "outputs": [ { @@ -1684,4 +1723,4 @@ "inputs": [], "anonymous": false } -] \ No newline at end of file +] diff --git a/contracts/BSCValidatorSet.sol b/contracts/BSCValidatorSet.sol index 91cf59ba6..25dbc7642 100644 --- a/contracts/BSCValidatorSet.sol +++ b/contracts/BSCValidatorSet.sol @@ -84,7 +84,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica uint256 public constant INIT_SYSTEM_REWARD_RATIO = 625; // 625/10000 is 1/16 uint256 public constant MAX_SYSTEM_REWARD_BALANCE = 100 ether; - uint256 public systemRewardRatio; + uint256 public initSystemRewardRatio; uint256 public previousHeight; uint256 public previousBalanceOfSystemReward; // deprecated bytes[] public previousVoteAddrFullSet; @@ -95,6 +95,10 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica Validator[] private _tmpMigratedValidatorSet; bytes[] private _tmpMigratedVoteAddrs; + // BEP-341 Validators can produce consecutive blocks + uint256 public turnTerm; + uint256 public antiMEVSystemRewardRatio; + struct Validator { address consensusAddress; address payable feeAddress; @@ -331,11 +335,16 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica uint256 index = currentValidatorSetMap[valAddr]; if (isSystemRewardIncluded == false) { - systemRewardRatio = INIT_SYSTEM_REWARD_RATIO; + initSystemRewardRatio = INIT_SYSTEM_REWARD_RATIO; burnRatio = INIT_BURN_RATIO; isSystemRewardIncluded = true; } + uint256 systemRewardRatio = initSystemRewardRatio; + if (turnTerm > 1 && antiMEVSystemRewardRatio > 0) { + systemRewardRatio += antiMEVSystemRewardRatio * (block.number % turnTerm) / (turnTerm - 1); + } + if (value > 0 && systemRewardRatio > 0) { uint256 toSystemReward = msg.value.mul(systemRewardRatio).div(BLOCK_FEES_RATIO_SCALE); if (toSystemReward > 0) { @@ -697,8 +706,8 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica require(value.length == 32, "length of burnRatio mismatch"); uint256 newBurnRatio = BytesToTypes.bytesToUint256(32, value); require( - newBurnRatio.add(systemRewardRatio) <= BLOCK_FEES_RATIO_SCALE, - "the burnRatio plus systemRewardRatio must be no greater than 10000" + newBurnRatio.add(initSystemRewardRatio).add(antiMEVSystemRewardRatio) <= BLOCK_FEES_RATIO_SCALE, + "the burnRatio plus initSystemRewardRatio and antiMEVSystemRewardRatio must be no greater than 10000" ); burnRatio = newBurnRatio; } else if (Memory.compareStrings(key, "maxNumOfMaintaining")) { @@ -741,14 +750,30 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica newNumOfCabinets <= MAX_NUM_OF_VALIDATORS, "the numOfCabinets must be less than MAX_NUM_OF_VALIDATORS" ); numOfCabinets = newNumOfCabinets; - } else if (Memory.compareStrings(key, "systemRewardRatio")) { - require(value.length == 32, "length of systemRewardRatio mismatch"); - uint256 newSystemRewardRatio = BytesToTypes.bytesToUint256(32, value); + } else if (Memory.compareStrings(key, "initSystemRewardRatio")) { + require(value.length == 32, "length of initSystemRewardRatio mismatch"); + uint256 newInitSystemRewardRatio = BytesToTypes.bytesToUint256(32, value); + require( + newInitSystemRewardRatio.add(burnRatio).add(antiMEVSystemRewardRatio) <= BLOCK_FEES_RATIO_SCALE, + "the initSystemRewardRatio plus burnRatio and antiMEVSystemRewardRatio must be no greater than 10000" + ); + initSystemRewardRatio = newInitSystemRewardRatio; + } else if (Memory.compareStrings(key, "antiMEVSystemRewardRatio")) { + require(value.length == 32, "length of antiMEVSystemRewardRatio mismatch"); + uint256 newAntiMEVSystemRewardRatio = BytesToTypes.bytesToUint256(32, value); require( - newSystemRewardRatio.add(burnRatio) <= BLOCK_FEES_RATIO_SCALE, - "the systemRewardRatio plus burnRatio must be no greater than 10000" + newAntiMEVSystemRewardRatio.add(burnRatio).add(initSystemRewardRatio) <= BLOCK_FEES_RATIO_SCALE, + "the antiMEVSystemRewardRatio plus burnRatio and initSystemRewardRatio must be no greater than 10000" ); - systemRewardRatio = newSystemRewardRatio; + antiMEVSystemRewardRatio = newAntiMEVSystemRewardRatio; + } else if (Memory.compareStrings(key, "turnTerm")) { + require(value.length == 32, "length of turnTerm mismatch"); + uint256 newTurnTerm = BytesToTypes.bytesToUint256(32, value); + require( + newTurnTerm >= 3 && newTurnTerm <= 9 || newTurnTerm == 1, + "the turnTerm should be in [3,9] or equal to 1" + ); + turnTerm = newTurnTerm; } else { require(false, "unknown param"); } @@ -1047,6 +1072,13 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica return voteAddrs; } + function getTurnTerm() external view returns (uint256) { + if (turnTerm == 0) { + return 1; + } + return turnTerm; + } + function setPreviousVoteAddrFullSet() private { uint256 n = previousVoteAddrFullSet.length; uint256 m = currentVoteAddrFullSet.length; diff --git a/test/SlashIndicator.t.sol b/test/SlashIndicator.t.sol index 278a34bd8..c1677ae04 100644 --- a/test/SlashIndicator.t.sol +++ b/test/SlashIndicator.t.sol @@ -8,7 +8,7 @@ contract SlashIndicatorTest is Deployer { uint256 public burnRatio; uint256 public burnRatioScale; - uint256 public systemRewardRatio; + uint256 public initSystemRewardRatio; uint256 public systemRewardRatioScale; address public coinbase; @@ -19,8 +19,8 @@ contract SlashIndicatorTest is Deployer { bscValidatorSet.isSystemRewardIncluded() ? bscValidatorSet.burnRatio() : bscValidatorSet.INIT_BURN_RATIO(); burnRatioScale = bscValidatorSet.BLOCK_FEES_RATIO_SCALE(); - systemRewardRatio = bscValidatorSet.isSystemRewardIncluded() - ? bscValidatorSet.systemRewardRatio() + initSystemRewardRatio = bscValidatorSet.isSystemRewardIncluded() + ? bscValidatorSet.initSystemRewardRatio() : bscValidatorSet.INIT_SYSTEM_REWARD_RATIO(); systemRewardRatioScale = bscValidatorSet.BLOCK_FEES_RATIO_SCALE(); @@ -356,7 +356,7 @@ contract SlashIndicatorTest is Deployer { } function _calcIncoming(uint256 value) internal view returns (uint256 incoming) { - uint256 toSystemReward = (value * systemRewardRatio) / systemRewardRatioScale; + uint256 toSystemReward = (value * initSystemRewardRatio) / systemRewardRatioScale; uint256 toBurn = (value * burnRatio) / burnRatioScale; incoming = value - toSystemReward - toBurn; } diff --git a/test/ValidatorSet.t.sol b/test/ValidatorSet.t.sol index b101a1141..1c0a4b913 100644 --- a/test/ValidatorSet.t.sol +++ b/test/ValidatorSet.t.sol @@ -23,7 +23,7 @@ contract ValidatorSetTest is Deployer { uint256 public burnRatioScale; uint256 public maxNumOfWorkingCandidates; uint256 public numOfCabinets; - uint256 public systemRewardRatio; + uint256 public initSystemRewardRatio; uint256 public systemRewardRatioScale; address public coinbase; @@ -42,8 +42,8 @@ contract ValidatorSetTest is Deployer { burnRatio = bscValidatorSet.isSystemRewardIncluded() ? bscValidatorSet.burnRatio() : bscValidatorSet.INIT_BURN_RATIO(); burnRatioScale = bscValidatorSet.BLOCK_FEES_RATIO_SCALE(); - systemRewardRatio = bscValidatorSet.isSystemRewardIncluded() - ? bscValidatorSet.systemRewardRatio() + initSystemRewardRatio = bscValidatorSet.isSystemRewardIncluded() + ? bscValidatorSet.initSystemRewardRatio() : bscValidatorSet.INIT_SYSTEM_REWARD_RATIO(); systemRewardRatioScale = bscValidatorSet.BLOCK_FEES_RATIO_SCALE(); totalInComing = bscValidatorSet.totalInComing(); @@ -615,7 +615,7 @@ contract ValidatorSetTest is Deployer { } function _calcIncoming(uint256 value) internal view returns (uint256 incoming) { - uint256 toSystemReward = (value * systemRewardRatio) / systemRewardRatioScale; + uint256 toSystemReward = (value * initSystemRewardRatio) / systemRewardRatioScale; uint256 toBurn = (value * burnRatio) / burnRatioScale; incoming = value - toSystemReward - toBurn; } diff --git a/test/utils/interface/IBSCValidatorSet.sol b/test/utils/interface/IBSCValidatorSet.sol index 960be0788..f907b8140 100644 --- a/test/utils/interface/IBSCValidatorSet.sol +++ b/test/utils/interface/IBSCValidatorSet.sol @@ -108,6 +108,7 @@ interface BSCValidatorSet { function handleFailAckPackage(uint8 channelId, bytes memory msgBytes) external; function handleSynPackage(uint8, bytes memory msgBytes) external returns (bytes memory responsePayload); function init() external; + function initSystemRewardRatio() external view returns (uint256); function isCurrentValidator(address validator) external view returns (bool); function isMonitoredForMaliciousVote(bytes memory voteAddr) external view returns (bool); function isSystemRewardIncluded() external view returns (bool); @@ -124,7 +125,6 @@ interface BSCValidatorSet { function previousHeight() external view returns (uint256); function previousVoteAddrFullSet(uint256) external view returns (bytes memory); function removeTmpMigratedValidator(address validator) external; - function systemRewardRatio() external view returns (uint256); function totalInComing() external view returns (uint256); function updateParam(string memory key, bytes memory value) external; function updateValidatorSetV2(