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

feat: define turnLength and systemRewardAntiMEVRatio for BEP-341 #562

Merged
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
43 changes: 41 additions & 2 deletions abi/bscvalidatorset.abi
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,19 @@
],
"stateMutability": "view"
},
{
"type": "function",
"name": "getTurnLength",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "getValidators",
Expand Down Expand Up @@ -1239,7 +1252,20 @@
},
{
"type": "function",
"name": "systemRewardRatio",
"name": "systemRewardAntiMEVRatio",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "systemRewardBaseRatio",
"inputs": [],
"outputs": [
{
Expand All @@ -1263,6 +1289,19 @@
],
"stateMutability": "view"
},
{
"type": "function",
"name": "turnLength",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "updateParam",
Expand Down Expand Up @@ -1684,4 +1723,4 @@
"inputs": [],
"anonymous": false
}
]
]
52 changes: 42 additions & 10 deletions contracts/BSCValidatorSet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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 systemRewardBaseRatio;
uint256 public previousHeight;
uint256 public previousBalanceOfSystemReward; // deprecated
bytes[] public previousVoteAddrFullSet;
Expand All @@ -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 turnLength; // Consecutive number of blocks a validator receives priority for block production
uint256 public systemRewardAntiMEVRatio;

struct Validator {
address consensusAddress;
address payable feeAddress;
Expand Down Expand Up @@ -331,11 +335,16 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica
uint256 index = currentValidatorSetMap[valAddr];

if (isSystemRewardIncluded == false) {
systemRewardRatio = INIT_SYSTEM_REWARD_RATIO;
systemRewardBaseRatio = INIT_SYSTEM_REWARD_RATIO;
burnRatio = INIT_BURN_RATIO;
isSystemRewardIncluded = true;
}

uint256 systemRewardRatio = systemRewardBaseRatio;
if (turnLength > 1 && systemRewardAntiMEVRatio > 0) {
systemRewardRatio += systemRewardAntiMEVRatio * (block.number % turnLength) / (turnLength - 1);
}

if (value > 0 && systemRewardRatio > 0) {
uint256 toSystemReward = msg.value.mul(systemRewardRatio).div(BLOCK_FEES_RATIO_SCALE);
if (toSystemReward > 0) {
Expand Down Expand Up @@ -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(systemRewardBaseRatio).add(systemRewardAntiMEVRatio) <= BLOCK_FEES_RATIO_SCALE,
"the burnRatio plus systemRewardBaseRatio and systemRewardAntiMEVRatio must be no greater than 10000"
);
burnRatio = newBurnRatio;
} else if (Memory.compareStrings(key, "maxNumOfMaintaining")) {
Expand Down Expand Up @@ -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, "systemRewardBaseRatio")) {
require(value.length == 32, "length of systemRewardBaseRatio mismatch");
uint256 newSystemRewardBaseRatio = BytesToTypes.bytesToUint256(32, value);
require(
newSystemRewardBaseRatio.add(burnRatio).add(systemRewardAntiMEVRatio) <= BLOCK_FEES_RATIO_SCALE,
"the systemRewardBaseRatio plus burnRatio and systemRewardAntiMEVRatio must be no greater than 10000"
);
systemRewardBaseRatio = newSystemRewardBaseRatio;
} else if (Memory.compareStrings(key, "systemRewardAntiMEVRatio")) {
require(value.length == 32, "length of systemRewardAntiMEVRatio mismatch");
uint256 newSystemRewardAntiMEVRatio = BytesToTypes.bytesToUint256(32, value);
require(
newSystemRewardRatio.add(burnRatio) <= BLOCK_FEES_RATIO_SCALE,
"the systemRewardRatio plus burnRatio must be no greater than 10000"
newSystemRewardAntiMEVRatio.add(burnRatio).add(systemRewardBaseRatio) <= BLOCK_FEES_RATIO_SCALE,
"the systemRewardAntiMEVRatio plus burnRatio and systemRewardBaseRatio must be no greater than 10000"
);
systemRewardRatio = newSystemRewardRatio;
systemRewardAntiMEVRatio = newSystemRewardAntiMEVRatio;
} else if (Memory.compareStrings(key, "turnLength")) {
require(value.length == 32, "length of turnLength mismatch");
uint256 newTurnLength = BytesToTypes.bytesToUint256(32, value);
require(
newTurnLength >= 3 && newTurnLength <= 9 || newTurnLength == 1,
"the turnLength should be in [3,9] or equal to 1"
);
turnLength = newTurnLength;
} else {
require(false, "unknown param");
}
Expand Down Expand Up @@ -1047,6 +1072,13 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica
return voteAddrs;
}

function getTurnLength() external view returns (uint256) {
if (turnLength == 0) {
return 1;
}
return turnLength;
}

function setPreviousVoteAddrFullSet() private {
uint256 n = previousVoteAddrFullSet.length;
uint256 m = currentVoteAddrFullSet.length;
Expand Down
14 changes: 10 additions & 4 deletions test/SlashIndicator.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ contract SlashIndicatorTest is Deployer {

uint256 public burnRatio;
uint256 public burnRatioScale;
uint256 public systemRewardRatio;
uint256 public systemRewardBaseRatio;
uint256 public systemRewardRatioScale;

address public coinbase;
Expand All @@ -20,8 +20,8 @@ contract SlashIndicatorTest is Deployer {
bscValidatorSet.isSystemRewardIncluded() ? bscValidatorSet.burnRatio() : bscValidatorSet.INIT_BURN_RATIO();
burnRatioScale = bscValidatorSet.BLOCK_FEES_RATIO_SCALE();

systemRewardRatio = bscValidatorSet.isSystemRewardIncluded()
? bscValidatorSet.systemRewardRatio()
systemRewardBaseRatio = bscValidatorSet.isSystemRewardIncluded()
? bscValidatorSet.systemRewardBaseRatio()
: bscValidatorSet.INIT_SYSTEM_REWARD_RATIO();
systemRewardRatioScale = bscValidatorSet.BLOCK_FEES_RATIO_SCALE();

Expand Down Expand Up @@ -434,7 +434,13 @@ contract SlashIndicatorTest is Deployer {
}

function _calcIncoming(uint256 value) internal view returns (uint256 incoming) {
uint256 toSystemReward = (value * systemRewardRatio) / systemRewardRatioScale;
uint256 turnLength = bscValidatorSet.getTurnLength();
uint256 systemRewardAntiMEVRatio = bscValidatorSet.systemRewardAntiMEVRatio();
uint256 systemRewardRatio = systemRewardBaseRatio;
if (turnLength > 1 && systemRewardAntiMEVRatio > 0) {
systemRewardRatio += systemRewardAntiMEVRatio * (block.number % turnLength) / (turnLength - 1);
}
uint256 toSystemReward = (value * systemRewardBaseRatio) / systemRewardRatioScale;
uint256 toBurn = (value * burnRatio) / burnRatioScale;
incoming = value - toSystemReward - toBurn;
}
Expand Down
43 changes: 36 additions & 7 deletions test/ValidatorSet.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ contract ValidatorSetTest is Deployer {
uint256 public burnRatioScale;
uint256 public maxNumOfWorkingCandidates;
uint256 public numOfCabinets;
uint256 public systemRewardRatio;
uint256 public systemRewardBaseRatio;
uint256 public systemRewardRatioScale;

address public coinbase;
Expand All @@ -39,8 +39,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()
systemRewardBaseRatio = bscValidatorSet.isSystemRewardIncluded()
? bscValidatorSet.systemRewardBaseRatio()
: bscValidatorSet.INIT_SYSTEM_REWARD_RATIO();
systemRewardRatioScale = bscValidatorSet.BLOCK_FEES_RATIO_SCALE();
totalInComing = bscValidatorSet.totalInComing();
Expand Down Expand Up @@ -78,17 +78,35 @@ contract ValidatorSetTest is Deployer {
vm.expectRevert("deposit value is zero");
bscValidatorSet.deposit(validator0);

uint256 realAmount = _calcIncoming(amount);
uint256 realAmount0 = _calcIncoming(amount);
vm.expectEmit(true, false, false, true, address(bscValidatorSet));
emit validatorDeposit(validator0, realAmount);
emit validatorDeposit(validator0, realAmount0);
bscValidatorSet.deposit{ value: amount }(validator0);

vm.stopPrank();
assertEq(bscValidatorSet.getTurnLength(), 1);
bytes memory key = "turnLength";
bytes memory value = bytes(hex"0000000000000000000000000000000000000000000000000000000000000005"); // 5
_updateParamByGovHub(key, value, address(bscValidatorSet));
assertEq(bscValidatorSet.getTurnLength(), 5);

key = "systemRewardAntiMEVRatio";
value = bytes(hex"0000000000000000000000000000000000000000000000000000000000000200"); // 512
_updateParamByGovHub(key, value, address(bscValidatorSet));
assertEq(bscValidatorSet.systemRewardAntiMEVRatio(), 512);
vm.startPrank(coinbase);

uint256 realAmount1 = _calcIncoming(amount);
vm.expectEmit(true, false, false, true, address(bscValidatorSet));
emit validatorDeposit(validator0, realAmount1);
bscValidatorSet.deposit{ value: amount }(validator0);

address newAccount = _getNextUserAddress();
vm.expectEmit(true, false, false, true, address(bscValidatorSet));
emit deprecatedDeposit(newAccount, realAmount);
emit deprecatedDeposit(newAccount, realAmount1);
bscValidatorSet.deposit{ value: amount }(newAccount);

assertEq(bscValidatorSet.totalInComing(), totalInComing + realAmount);
assertEq(bscValidatorSet.totalInComing(), totalInComing + realAmount0 + realAmount1);
vm.stopPrank();
}

Expand All @@ -109,6 +127,11 @@ contract ValidatorSetTest is Deployer {
_updateParamByGovHub(key, value, address(bscValidatorSet));
assertEq(bscValidatorSet.maxNumOfCandidates(), 5);
assertEq(bscValidatorSet.maxNumOfWorkingCandidates(), 5);

key = "systemRewardBaseRatio";
value = bytes(hex"0000000000000000000000000000000000000000000000000000000000000400"); // 1024
_updateParamByGovHub(key, value, address(bscValidatorSet));
assertEq(bscValidatorSet.systemRewardBaseRatio(), 1024);
}

function testValidateSetChange() public {
Expand Down Expand Up @@ -284,6 +307,12 @@ contract ValidatorSetTest is Deployer {
}

function _calcIncoming(uint256 value) internal view returns (uint256 incoming) {
uint256 turnLength = bscValidatorSet.getTurnLength();
uint256 systemRewardAntiMEVRatio = bscValidatorSet.systemRewardAntiMEVRatio();
uint256 systemRewardRatio = systemRewardBaseRatio;
if (turnLength > 1 && systemRewardAntiMEVRatio > 0) {
systemRewardRatio += systemRewardAntiMEVRatio * (block.number % turnLength) / (turnLength - 1);
}
uint256 toSystemReward = (value * systemRewardRatio) / systemRewardRatioScale;
uint256 toBurn = (value * burnRatio) / burnRatioScale;
incoming = value - toSystemReward - toBurn;
Expand Down
5 changes: 4 additions & 1 deletion test/utils/interface/IBSCValidatorSet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ interface BSCValidatorSet {
function VALIDATORS_UPDATE_MESSAGE_TYPE() external view returns (uint8);
function VALIDATOR_CONTRACT_ADDR() external view returns (address);
function alreadyInit() external view returns (bool);
function systemRewardAntiMEVRatio() external view returns (uint256);
function bscChainID() external view returns (uint16);
function burnRatio() external view returns (uint256);
function burnRatioInitialized() external view returns (bool);
Expand Down Expand Up @@ -102,12 +103,14 @@ interface BSCValidatorSet {
function getIncoming(address validator) external view returns (uint256);
function getLivingValidators() external view returns (address[] memory, bytes[] memory);
function getMiningValidators() external view returns (address[] memory, bytes[] memory);
function getTurnLength() external view returns (uint256);
function getValidators() external view returns (address[] memory);
function getWorkingValidatorCount() external view returns (uint256 workingValidatorCount);
function handleAckPackage(uint8 channelId, bytes memory msgBytes) external;
function handleFailAckPackage(uint8 channelId, bytes memory msgBytes) external;
function handleSynPackage(uint8, bytes memory msgBytes) external returns (bytes memory responsePayload);
function init() external;
function systemRewardBaseRatio() 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);
Expand All @@ -124,8 +127,8 @@ 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 turnLength() external view returns (uint256);
function updateParam(string memory key, bytes memory value) external;
function updateValidatorSetV2(
address[] memory _consensusAddrs,
Expand Down
Loading