From dae2413c4c810f42b721886b8a537d9971696264 Mon Sep 17 00:00:00 2001 From: Galaxy <30950645+GalaxySciTech@users.noreply.github.com> Date: Mon, 26 Feb 2024 11:44:43 +0400 Subject: [PATCH] Update XDCValidator.sol --- contracts/validator/contract/XDCValidator.sol | 234 ++++++++++++------ 1 file changed, 163 insertions(+), 71 deletions(-) diff --git a/contracts/validator/contract/XDCValidator.sol b/contracts/validator/contract/XDCValidator.sol index 0e67746a17..0dd2c1e5d6 100644 --- a/contracts/validator/contract/XDCValidator.sol +++ b/contracts/validator/contract/XDCValidator.sol @@ -1,9 +1,7 @@ - pragma solidity ^0.4.21; import "./libs/SafeMath.sol"; - contract XDCValidator { using SafeMath for uint256; @@ -12,7 +10,7 @@ contract XDCValidator { event Propose(address _owner, address _candidate, uint256 _cap); event Resign(address _owner, address _candidate); event Withdraw(address _owner, uint256 _blockNumber, uint256 _cap); - event UploadedKYC(address _owner,string kycHash); + event UploadedKYC(address _owner, string kycHash); event InvalidatedNode(address _masternodeOwner, address[] _masternodes); struct ValidatorState { @@ -23,8 +21,8 @@ contract XDCValidator { } struct WithdrawState { - mapping(uint256 => uint256) caps; - uint256[] blockNumbers; + mapping(uint256 => uint256) caps; + uint256[] blockNumbers; } mapping(address => WithdrawState) withdrawsState; @@ -42,28 +40,30 @@ contract XDCValidator { address[] public candidates; uint256 public candidateCount = 0; - uint256 public ownerCount =0; + uint256 public ownerCount = 0; uint256 public minCandidateCap; uint256 public minVoterCap; uint256 public maxValidatorNumber; uint256 public candidateWithdrawDelay; uint256 public voterWithdrawDelay; - modifier onlyValidCandidateCap { + modifier onlyValidCandidateCap() { // anyone can deposit X XDC to become a candidate require(msg.value >= minCandidateCap); _; } - modifier onlyValidVoterCap { - + modifier onlyValidVoterCap() { require(msg.value >= minVoterCap); _; } - modifier onlyKYCWhitelisted { - require(KYCString[msg.sender].length!=0 || ownerToCandidate[msg.sender].length>0); - _; + modifier onlyKYCWhitelisted() { + require( + KYCString[msg.sender].length != 0 || + ownerToCandidate[msg.sender].length > 0 + ); + _; } modifier onlyOwner(address _candidate) { @@ -76,33 +76,38 @@ contract XDCValidator { _; } - modifier onlyValidCandidate (address _candidate) { + modifier onlyValidCandidate(address _candidate) { require(validatorsState[_candidate].isCandidate); _; } - modifier onlyNotCandidate (address _candidate) { + modifier onlyNotCandidate(address _candidate) { require(!validatorsState[_candidate].isCandidate); _; } - modifier onlyValidVote (address _candidate, uint256 _cap) { + modifier onlyValidVote(address _candidate, uint256 _cap) { require(validatorsState[_candidate].voters[msg.sender] >= _cap); if (validatorsState[_candidate].owner == msg.sender) { - require(validatorsState[_candidate].voters[msg.sender].sub(_cap) >= minCandidateCap); + require( + validatorsState[_candidate].voters[msg.sender].sub(_cap) >= + minCandidateCap + ); } _; } - modifier onlyValidWithdraw (uint256 _blockNumber, uint _index) { + modifier onlyValidWithdraw(uint256 _blockNumber, uint _index) { require(_blockNumber > 0); require(block.number >= _blockNumber); require(withdrawsState[msg.sender].caps[_blockNumber] > 0); - require(withdrawsState[msg.sender].blockNumbers[_index] == _blockNumber); + require( + withdrawsState[msg.sender].blockNumbers[_index] == _blockNumber + ); _; } - function XDCValidator ( + function XDCValidator( address[] _candidates, uint256[] _caps, address _firstOwner, @@ -129,19 +134,28 @@ contract XDCValidator { }); voters[_candidates[i]].push(_firstOwner); ownerToCandidate[_firstOwner].push(_candidates[i]); - validatorsState[_candidates[i]].voters[_firstOwner] = minCandidateCap; + validatorsState[_candidates[i]].voters[ + _firstOwner + ] = minCandidateCap; } } - // uploadKYC : anyone can upload a KYC; its not equivalent to becoming an owner. function uploadKYC(string kychash) external { KYCString[msg.sender].push(kychash); - emit UploadedKYC(msg.sender,kychash); + emit UploadedKYC(msg.sender, kychash); } // propose : any non-candidate who has uploaded its KYC can become an owner by proposing a candidate. - function propose(address _candidate) external payable onlyValidCandidateCap onlyKYCWhitelisted onlyNotCandidate(_candidate) { + function propose( + address _candidate + ) + external + payable + onlyValidCandidateCap + onlyKYCWhitelisted + onlyNotCandidate(_candidate) + { uint256 cap = validatorsState[_candidate].cap.add(msg.value); candidates.push(_candidate); validatorsState[_candidate] = ValidatorState({ @@ -149,9 +163,11 @@ contract XDCValidator { isCandidate: true, cap: cap }); - validatorsState[_candidate].voters[msg.sender] = validatorsState[_candidate].voters[msg.sender].add(msg.value); + validatorsState[_candidate].voters[msg.sender] = validatorsState[ + _candidate + ].voters[msg.sender].add(msg.value); candidateCount = candidateCount.add(1); - if (ownerToCandidate[msg.sender].length ==0){ + if (ownerToCandidate[msg.sender].length == 0) { owners.push(msg.sender); ownerCount++; } @@ -160,144 +176,220 @@ contract XDCValidator { emit Propose(msg.sender, _candidate, msg.value); } - function vote(address _candidate) external payable onlyValidVoterCap onlyValidCandidate(_candidate) { - validatorsState[_candidate].cap = validatorsState[_candidate].cap.add(msg.value); + function vote( + address _candidate + ) external payable onlyValidVoterCap onlyValidCandidate(_candidate) { + validatorsState[_candidate].cap = validatorsState[_candidate].cap.add( + msg.value + ); if (validatorsState[_candidate].voters[msg.sender] == 0) { voters[_candidate].push(msg.sender); } - validatorsState[_candidate].voters[msg.sender] = validatorsState[_candidate].voters[msg.sender].add(msg.value); + validatorsState[_candidate].voters[msg.sender] = validatorsState[ + _candidate + ].voters[msg.sender].add(msg.value); emit Vote(msg.sender, _candidate, msg.value); } - function getCandidates() public view returns(address[]) { + function getCandidates() public view returns (address[]) { return candidates; } - function getCandidateCap(address _candidate) public view returns(uint256) { + function getCandidateCap(address _candidate) public view returns (uint256) { return validatorsState[_candidate].cap; } - function getCandidateOwner(address _candidate) public view returns(address) { + function getCandidateOwner( + address _candidate + ) public view returns (address) { return validatorsState[_candidate].owner; } - function getVoterCap(address _candidate, address _voter) public view returns(uint256) { + function getVoterCap( + address _candidate, + address _voter + ) public view returns (uint256) { return validatorsState[_candidate].voters[_voter]; } - function getVoters(address _candidate) public view returns(address[]) { + function getVoters(address _candidate) public view returns (address[]) { return voters[_candidate]; } - function isCandidate(address _candidate) public view returns(bool) { + function isCandidate(address _candidate) public view returns (bool) { return validatorsState[_candidate].isCandidate; } - function getWithdrawBlockNumbers() public view returns(uint256[]) { + function getWithdrawBlockNumbers() public view returns (uint256[]) { return withdrawsState[msg.sender].blockNumbers; } - function getWithdrawCap(uint256 _blockNumber) public view returns(uint256) { + function getWithdrawCap( + uint256 _blockNumber + ) public view returns (uint256) { return withdrawsState[msg.sender].caps[_blockNumber]; } - function unvote(address _candidate, uint256 _cap) public onlyValidVote(_candidate, _cap) { - validatorsState[_candidate].cap = validatorsState[_candidate].cap.sub(_cap); - validatorsState[_candidate].voters[msg.sender] = validatorsState[_candidate].voters[msg.sender].sub(_cap); + function unvote( + address _candidate, + uint256 _cap + ) public onlyValidVote(_candidate, _cap) { + validatorsState[_candidate].cap = validatorsState[_candidate].cap.sub( + _cap + ); + validatorsState[_candidate].voters[msg.sender] = validatorsState[ + _candidate + ].voters[msg.sender].sub(_cap); // refund after delay X blocks uint256 withdrawBlockNumber = voterWithdrawDelay.add(block.number); - withdrawsState[msg.sender].caps[withdrawBlockNumber] = withdrawsState[msg.sender].caps[withdrawBlockNumber].add(_cap); + withdrawsState[msg.sender].caps[withdrawBlockNumber] = withdrawsState[ + msg.sender + ].caps[withdrawBlockNumber].add(_cap); withdrawsState[msg.sender].blockNumbers.push(withdrawBlockNumber); emit Unvote(msg.sender, _candidate, _cap); } - function resign(address _candidate) public onlyOwner(_candidate) onlyCandidate(_candidate) { + function resign( + address _candidate + ) public onlyOwner(_candidate) onlyCandidate(_candidate) { validatorsState[_candidate].isCandidate = false; candidateCount = candidateCount.sub(1); for (uint256 i = 0; i < candidates.length; i++) { if (candidates[i] == _candidate) { + address[] memory cacheArray = ownerToCandidate[msg.sender]; + uint256 cacheArrayLength = cacheArray.length; + for (uint256 j = 0; j < cacheArrayLength; j++) { + if (cacheArray[j] == _candidate) { + delete cacheArray[j]; + } + } + ownerToCandidate[msg.sender] = removeZeroAddresses(cacheArray); + if (ownerToCandidate[msg.sender].length == 0) { + ownerCount--; + } delete candidates[i]; break; } } + candidates = removeZeroAddresses(candidates); uint256 cap = validatorsState[_candidate].voters[msg.sender]; - validatorsState[_candidate].cap = validatorsState[_candidate].cap.sub(cap); + validatorsState[_candidate].cap = validatorsState[_candidate].cap.sub( + cap + ); validatorsState[_candidate].voters[msg.sender] = 0; // refunding after resigning X blocks uint256 withdrawBlockNumber = candidateWithdrawDelay.add(block.number); - withdrawsState[msg.sender].caps[withdrawBlockNumber] = withdrawsState[msg.sender].caps[withdrawBlockNumber].add(cap); + withdrawsState[msg.sender].caps[withdrawBlockNumber] = withdrawsState[ + msg.sender + ].caps[withdrawBlockNumber].add(cap); withdrawsState[msg.sender].blockNumbers.push(withdrawBlockNumber); emit Resign(msg.sender, _candidate); } // voteInvalidKYC : any candidate can vote for invalid KYC i.e. a particular candidate's owner has uploaded a bad KYC. // On securing 75% votes against an owner ( not candidate ), owner & all its candidates will lose their funds. - function voteInvalidKYC(address _invalidCandidate) onlyValidCandidate(msg.sender) onlyValidCandidate(_invalidCandidate) public { + function voteInvalidKYC( + address _invalidCandidate + ) + public + onlyValidCandidate(msg.sender) + onlyValidCandidate(_invalidCandidate) + { address candidateOwner = getCandidateOwner(msg.sender); address _invalidMasternode = getCandidateOwner(_invalidCandidate); require(!hasVotedInvalid[candidateOwner][_invalidMasternode]); hasVotedInvalid[candidateOwner][_invalidMasternode] = true; invalidKYCCount[_invalidMasternode] += 1; - if( invalidKYCCount[_invalidMasternode]*100/getOwnerCount() >= 75 ){ + if ( + (invalidKYCCount[_invalidMasternode] * 100) / getOwnerCount() >= 75 + ) { // 75% owners say that the KYC is invalid - address[] memory allMasternodes = new address[](candidates.length-1) ; - uint count=0; - for (uint i=0;i