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

chore: add check for moniker and update script #445

Merged
merged 1 commit into from
Dec 14, 2023
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
5 changes: 5 additions & 0 deletions abi/stakehub.abi
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,11 @@
"name": "DuplicateConsensusAddress",
"inputs": []
},
{
"type": "error",
"name": "DuplicateMoniker",
"inputs": []
},
{
"type": "error",
"name": "DuplicateVoteAddress",
Expand Down
11 changes: 9 additions & 2 deletions contracts/BC_fusion/StakeHub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ contract StakeHub is System, Initializable {
error DuplicateConsensusAddress();
// @notice signature: 0x11fdb947
error DuplicateVoteAddress();
// @notice signature: 0xc0bf4143
error DuplicateMoniker();
// @notice signature: 0x2f64097e
error SelfDelegationNotEnough();
// @notice signature: 0xdc81db85
Expand Down Expand Up @@ -106,6 +108,8 @@ contract StakeHub is System, Initializable {
EnumerableSet.AddressSet private _validatorSet;
// validator operator address => validator info
mapping(address => Validator) private _validators;
// validator moniker set(hash of the moniker)
mapping(bytes32 => bool) private _monikerSet;
// validator consensus address => validator operator address
mapping(address => address) public consensusToOperator;
// validator consensus address => expiry date
Expand Down Expand Up @@ -277,6 +281,8 @@ contract StakeHub is System, Initializable {
if (voteToOperator[voteAddress] != address(0) || _legacyVoteAddress[voteAddress]) {
revert DuplicateVoteAddress();
}
bytes32 monikerHash = keccak256(abi.encodePacked(description.moniker));
if (_monikerSet[monikerHash]) revert DuplicateMoniker();

uint256 delegation = msg.value;
if (delegation < minSelfDelegationBNB + LOCK_AMOUNT) revert SelfDelegationNotEnough();
Expand All @@ -294,6 +300,7 @@ contract StakeHub is System, Initializable {
address creditContract = _deployStakeCredit(operatorAddress, description.moniker);

_validatorSet.add(operatorAddress);
_monikerSet[monikerHash] = true;
Validator storage valInfo = _validators[operatorAddress];
valInfo.consensusAddress = consensusAddress;
valInfo.operatorAddress = operatorAddress;
Expand Down Expand Up @@ -477,7 +484,7 @@ contract StakeHub is System, Initializable {
/**
* @param srcValidator the operator address of the validator to be redelegated from
* @param dstValidator the operator address of the validator to be redelegated to
* @param shares the shares to be redeloperatorAddressegated
* @param shares the shares to be redelegated
* @param delegateVotePower whether to delegate vote power to the dstValidator
*/
function redelegate(
Expand Down Expand Up @@ -954,7 +961,7 @@ contract StakeHub is System, Initializable {
return;
}
if (IStakeCredit(valInfo.creditContract).getPooledBNB(operatorAddress) < minSelfDelegationBNB) {
_jailValidator(valInfo, 0);
_jailValidator(valInfo, downtimeJailTime);
// need to inform BSCValidatorSet contract to remove the validator
IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).jailValidator(valInfo.consensusAddress);
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"scripts": {
"lint:check": "forge fmt ./contracts/BC_fusion --check",
"lint:write": "forge fmt ./contracts/BC_fusion",
"generate:dev": "poetry run python -m scripts.generate dev --breath-block-interval \"1 minutes\" --block-interval \"1 seconds\" --init-bc-consensus-addresses 'hex\"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc\"' --init-bc-vote-addresses 'hex\"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000030b86b3146bdd2200b1dbdb1cea5e40d3451c028cbb4fb03b1826f7f2d82bee76bbd5cd68a74a16a7eceea093fd5826b9200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003087ce273bb9b51fd69e50de7a8d9a99cfb3b1a5c6a7b85f6673d137a5a2ce7df3d6ee4e6d579a142d58b0606c4a7a1c27000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a33ac14980d85c0d154c5909ebf7a11d455f54beb4d5d0dc1d8b3670b9c4a6b6c450ee3d623ecc48026f09ed1f0b5c1200000000000000000000000000000000\"' --asset-protector \"0xdF87F0e2B8519Ea2DD4aBd8B639cdD628497eD25\" --unbond-period \"2 minutes\" --downtime-jail-time \"2 minutes\" --felony-jail-time \"3 minutes\" --init-voting-delay \"1 minutes / BLOCK_INTERVAL\" --init-voting-period \"2 minutes / BLOCK_INTERVAL\" --init-min-period-after-quorum \"uint64(1 minutes / BLOCK_INTERVAL)\" --governor-protector \"0xdF87F0e2B8519Ea2DD4aBd8B639cdD628497eD25\" --init-minimal-delay \"1 minutes\""
"generate:dev": "poetry run python -m scripts.generate dev --init-felony-slash-scope \"60\" --breathe-block-interval \"1 minutes\" --block-interval \"1 seconds\" --init-bc-consensus-addresses 'hex\"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc\"' --init-bc-vote-addresses 'hex\"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000030b86b3146bdd2200b1dbdb1cea5e40d3451c028cbb4fb03b1826f7f2d82bee76bbd5cd68a74a16a7eceea093fd5826b9200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003087ce273bb9b51fd69e50de7a8d9a99cfb3b1a5c6a7b85f6673d137a5a2ce7df3d6ee4e6d579a142d58b0606c4a7a1c27000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030a33ac14980d85c0d154c5909ebf7a11d455f54beb4d5d0dc1d8b3670b9c4a6b6c450ee3d623ecc48026f09ed1f0b5c1200000000000000000000000000000000\"' --asset-protector \"0xdF87F0e2B8519Ea2DD4aBd8B639cdD628497eD25\" --unbond-period \"2 minutes\" --downtime-jail-time \"2 minutes\" --felony-jail-time \"3 minutes\" --init-voting-delay \"1 minutes / BLOCK_INTERVAL\" --init-voting-period \"2 minutes / BLOCK_INTERVAL\" --init-min-period-after-quorum \"uint64(1 minutes / BLOCK_INTERVAL)\" --governor-protector \"0xdF87F0e2B8519Ea2DD4aBd8B639cdD628497eD25\" --init-minimal-delay \"1 minutes\""
},
"dependencies": {
"@openzeppelin/contracts": "^4.9.3",
Expand Down
17 changes: 10 additions & 7 deletions scripts/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,15 @@ def generate_relayer_hub(whitelist_1, whitelist_2):
insert(contract, "alreadyInit = true;", "\t\twhitelistInit();")


def generate_slash_indicator():
if network == "dev":
contract = "SlashIndicator.sol"
backup_file(
os.path.join(work_dir, "contracts", contract), os.path.join(work_dir, "contracts", contract[:-4] + ".bak")
)
def generate_slash_indicator(init_felony_slash_scope):
contract = "SlashIndicator.sol"
backup_file(
os.path.join(work_dir, "contracts", contract), os.path.join(work_dir, "contracts", contract[:-4] + ".bak")
)

replace_parameter(contract, "uint256 public constant INIT_FELONY_SLASH_SCOPE", f"{init_felony_slash_scope}")

if network == "dev":
insert(contract, "alreadyInit = true;", "\t\tenableMaliciousVoteSlash = true;")


Expand Down Expand Up @@ -348,6 +350,7 @@ def dev(
str, typer.Option(help="whitelist relayer2's address")] = "0x316b2Fa7C8a2ab7E21110a4B3f58771C01A71344",
source_chain_id: Annotated[
str, typer.Option(help="source chain id of the token recover portal")] = "Binance-Chain-Ganges",
init_felony_slash_scope: str = "86400",
breathe_block_interval: Annotated[str, typer.Option(help="breath block interval of Parlia")] = "1 days",
block_interval: Annotated[str, typer.Option(help="block interval of Parlia")] = "3 seconds",
init_bc_consensus_addresses:
Expand Down Expand Up @@ -390,7 +393,7 @@ def dev(
generate_system()
generate_cross_chain()
generate_system_reward()
generate_slash_indicator()
generate_slash_indicator(init_felony_slash_scope)
generate_relayer_hub(whitelist_1, whitelist_2)
generate_tendermint_light_client(init_consensus_bytes)
generate_validator_set(init_burn_ratio, init_validatorset_bytes)
Expand Down
63 changes: 54 additions & 9 deletions test/StakeHub.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,69 @@ contract StakeHubTest is Deployer {
stakeHub.initialize();
}

function testCreateAndEditValidator() public {
// 1. create validator
function testCreateValidator() public {
// create validator success
(address validator,) = _createValidator(2000 ether);
(address consensusAddress,,, bytes memory voteAddress,,) = stakeHub.getValidatorBasicInfo(validator);

// create failed with duplicate consensus address
uint256 delegation = 2000 ether;
address operatorAddress = _getNextUserAddress();
StakeHub.Commission memory commission = StakeHub.Commission({ rate: 10, maxRate: 100, maxChangeRate: 5 });
StakeHub.Description memory description = StakeHub.Description({
moniker: string.concat("T", vm.toString(uint24(uint160(operatorAddress)))),
identity: vm.toString(operatorAddress),
website: vm.toString(operatorAddress),
details: vm.toString(operatorAddress)
});
bytes memory blsPubKey = bytes.concat(
hex"00000000000000000000000000000000000000000000000000000000", abi.encodePacked(operatorAddress)
);
bytes memory blsProof = new bytes(96);

uint256 toLock = stakeHub.LOCK_AMOUNT();
vm.prank(operatorAddress);
vm.expectRevert();
stakeHub.createValidator{ value: delegation + toLock }(
consensusAddress, blsPubKey, blsProof, commission, description
);

// create failed with duplicate vote address
consensusAddress = address(uint160(uint256(keccak256(blsPubKey))));
vm.prank(operatorAddress);
vm.expectRevert();
stakeHub.createValidator{ value: delegation + toLock }(
consensusAddress, voteAddress, blsProof, commission, description
);

// create failed with duplicate moniker
description = stakeHub.getValidatorDescription(validator);
vm.prank(operatorAddress);
vm.expectRevert();
stakeHub.createValidator{ value: delegation + toLock }(
consensusAddress, voteAddress, blsProof, commission, description
);
}

function testEditValidator() public {
// create validator
(address validator,) = _createValidator(2000 ether);
vm.startPrank(validator);

// edit failed because of `UpdateTooFrequently`
vm.expectRevert();
stakeHub.editConsensusAddress(address(1));

// 2. edit consensus address
// edit consensus address
vm.warp(block.timestamp + 1 days);
address newConsensusAddress = address(0x1234);
vm.expectEmit(true, true, false, true, address(stakeHub));
emit ConsensusAddressEdited(validator, newConsensusAddress);
stakeHub.editConsensusAddress(newConsensusAddress);
(address realAddr,,,,,) = stakeHub.getValidatorBasicInfo(validator);
assertEq(realAddr, newConsensusAddress);
(address realConsensusAddr,,,,,) = stakeHub.getValidatorBasicInfo(validator);
assertEq(realConsensusAddr, newConsensusAddress);

// 3. edit commission rate
// edit commission rate
vm.warp(block.timestamp + 1 days);
vm.expectRevert();
stakeHub.editCommissionRate(110);
Expand All @@ -64,7 +109,7 @@ contract StakeHubTest is Deployer {
StakeHub.Commission memory realComm = stakeHub.getValidatorCommission(validator);
assertEq(realComm.rate, 15);

// 4. edit description
// edit description
vm.warp(block.timestamp + 1 days);
StakeHub.Description memory description = stakeHub.getValidatorDescription(validator);
description.moniker = "Test";
Expand All @@ -73,10 +118,10 @@ contract StakeHubTest is Deployer {
emit DescriptionEdited(validator);
stakeHub.editDescription(description);
StakeHub.Description memory realDesc = stakeHub.getValidatorDescription(validator);
assertNotEq(realDesc.moniker, "Test"); // edit moniker is not allowed
assertNotEq(realDesc.moniker, "Test"); // edit moniker will be ignored
assertEq(realDesc.website, "Test");

// 5. edit vote address
// edit vote address
vm.warp(block.timestamp + 1 days);
bytes memory newVoteAddress =
hex"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001234";
Expand Down
9 changes: 0 additions & 9 deletions test/utils/interface/IBSCValidatorSet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@
pragma solidity ^0.8.10;

interface BSCValidatorSet {
struct Validator {
address consensusAddress;
address payable feeAddress;
address BBCFeeAddress;
uint64 votingPower;
bool jailed;
uint256 incoming;
}

event batchTransfer(uint256 amount);
event batchTransferFailed(uint256 indexed amount, string reason);
event batchTransferLowerFailed(uint256 indexed amount, bytes reason);
Expand Down
1 change: 1 addition & 0 deletions test/utils/interface/IStakeHub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ interface StakeHub {
error ConsensusAddressExpired();
error DelegationAmountTooSmall();
error DuplicateConsensusAddress();
error DuplicateMoniker();
error DuplicateVoteAddress();
error InBlackList();
error InvalidCommission();
Expand Down
Loading