Skip to content

Commit

Permalink
chore: add check for moniker and update script
Browse files Browse the repository at this point in the history
  • Loading branch information
pythonberg1997 committed Dec 13, 2023
1 parent a964f98 commit 8a360be
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 19 deletions.
24 changes: 24 additions & 0 deletions abi/stakehub.abi
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,25 @@
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "isMonikerExisted",
"inputs": [
{
"name": "moniker",
"type": "string",
"internalType": "string"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "isPaused",
Expand Down Expand Up @@ -1342,6 +1361,11 @@
"name": "DuplicateConsensusAddress",
"inputs": []
},
{
"type": "error",
"name": "DuplicateMoniker",
"inputs": []
},
{
"type": "error",
"name": "DuplicateVoteAddress",
Expand Down
15 changes: 13 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 @@ -884,6 +891,10 @@ contract StakeHub is System, Initializable {
}
}

function isMonikerExisted(string calldata moniker) external view returns (bool) {
return _monikerSet[keccak256(abi.encodePacked(moniker))];
}

/*----------------- internal functions -----------------*/
function _checkMoniker(string memory moniker) internal pure returns (bool) {
bytes memory bz = bytes(moniker);
Expand Down Expand Up @@ -954,7 +965,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
2 changes: 2 additions & 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 Expand Up @@ -139,6 +140,7 @@ interface StakeHub {
function getValidatorRewardRecord(address operatorAddress, uint256 index) external view returns (uint256);
function getValidatorTotalPooledBNBRecord(address operatorAddress, uint256 index) external view returns (uint256);
function initialize() external;
function isMonikerExisted(string memory moniker) external view returns (bool);
function isPaused() external view returns (bool);
function maliciousVoteSlash(bytes memory voteAddress) external;
function maxElectedValidators() external view returns (uint256);
Expand Down

0 comments on commit 8a360be

Please sign in to comment.