tokenbridge-contracts/contracts/upgradeable_contracts/BaseBridgeValidators.sol

126 lines
4.5 KiB
Solidity

pragma solidity 0.4.24;
import "./Ownable.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./InitializableBridge.sol";
contract BaseBridgeValidators is InitializableBridge, Ownable {
using SafeMath for uint256;
address public constant F_ADDR = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF;
uint256 internal constant MAX_VALIDATORS = 50;
bytes32 internal constant REQUIRED_SIGNATURES = 0xd18ea17c351d6834a0e568067fb71804d2a588d5e26d60f792b1c724b1bd53b1; // keccak256(abi.encodePacked("requiredSignatures"))
bytes32 internal constant VALIDATOR_COUNT = 0x8656d603d9f985c3483946a92789d52202f49736384ba131cb92f62c4c1aa082; // keccak256(abi.encodePacked("validatorCount"))
event ValidatorAdded(address indexed validator);
event ValidatorRemoved(address indexed validator);
event RequiredSignaturesChanged(uint256 requiredSignatures);
function setRequiredSignatures(uint256 _requiredSignatures) external onlyOwner {
require(validatorCount() >= _requiredSignatures);
require(_requiredSignatures != 0);
uintStorage[REQUIRED_SIGNATURES] = _requiredSignatures;
emit RequiredSignaturesChanged(_requiredSignatures);
}
function getBridgeValidatorsInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
return (2, 3, 0);
}
function validatorList() external view returns (address[]) {
address[] memory list = new address[](validatorCount());
uint256 counter = 0;
address nextValidator = getNextValidator(F_ADDR);
require(nextValidator != address(0));
while (nextValidator != F_ADDR) {
list[counter] = nextValidator;
nextValidator = getNextValidator(nextValidator);
counter++;
require(nextValidator != address(0));
}
return list;
}
function _addValidator(address _validator) internal {
require(_validator != address(0) && _validator != F_ADDR);
require(!isValidator(_validator));
address firstValidator = getNextValidator(F_ADDR);
require(firstValidator != address(0));
setNextValidator(_validator, firstValidator);
setNextValidator(F_ADDR, _validator);
setValidatorCount(validatorCount().add(1));
}
function _removeValidator(address _validator) internal {
require(validatorCount() > requiredSignatures());
require(isValidator(_validator));
address validatorsNext = getNextValidator(_validator);
address index = F_ADDR;
address next = getNextValidator(index);
require(next != address(0));
while (next != _validator) {
index = next;
next = getNextValidator(index);
require(next != F_ADDR && next != address(0));
}
setNextValidator(index, validatorsNext);
deleteItemFromAddressStorage("validatorsList", _validator);
setValidatorCount(validatorCount().sub(1));
}
function requiredSignatures() public view returns (uint256) {
return uintStorage[REQUIRED_SIGNATURES];
}
function validatorCount() public view returns (uint256) {
return uintStorage[VALIDATOR_COUNT];
}
function isValidator(address _validator) public view returns (bool) {
return _validator != F_ADDR && getNextValidator(_validator) != address(0);
}
function getNextValidator(address _address) public view returns (address) {
return addressStorage[keccak256(abi.encodePacked("validatorsList", _address))];
}
function deleteItemFromAddressStorage(string _mapName, address _address) internal {
delete addressStorage[keccak256(abi.encodePacked(_mapName, _address))];
}
function setValidatorCount(uint256 _validatorCount) internal {
require(_validatorCount <= MAX_VALIDATORS);
uintStorage[VALIDATOR_COUNT] = _validatorCount;
}
function setNextValidator(address _prevValidator, address _validator) internal {
addressStorage[keccak256(abi.encodePacked("validatorsList", _prevValidator))] = _validator;
}
function isValidatorDuty(address _validator) external view returns (bool) {
uint256 counter = 0;
address next = getNextValidator(F_ADDR);
require(next != address(0));
while (next != F_ADDR) {
if (next == _validator) {
return (block.number % validatorCount() == counter);
}
next = getNextValidator(next);
counter++;
require(next != address(0));
}
return false;
}
}