diff --git a/wemix/governance-contract/.prettierrc b/wemix/governance-contract/.prettierrc new file mode 100644 index 000000000000..0929f3aa3532 --- /dev/null +++ b/wemix/governance-contract/.prettierrc @@ -0,0 +1,14 @@ +{ + "overrides": [ + { + "files": "*.sol", + "options": { + "printWidth": 150, + "tabWidth": 4, + "useTabs": false, + "singleQuote": false, + "bracketSpacing": true + } + } + ] +} \ No newline at end of file diff --git a/wemix/governance-contract/contracts/GovChecker.sol b/wemix/governance-contract/contracts/GovChecker.sol index 44d4720e9cc0..c8fef13b6597 100644 --- a/wemix/governance-contract/contracts/GovChecker.sol +++ b/wemix/governance-contract/contracts/GovChecker.sol @@ -10,83 +10,83 @@ import "./interface/IGov.sol"; * @dev GovChecker Contract that uses Registry contract */ contract GovChecker is OwnableUpgradeable { - IRegistry public reg; - - bytes32 public constant GOV_NAME = "GovernanceContract"; - bytes32 public constant STAKING_NAME = "Staking"; - bytes32 public constant BALLOT_STORAGE_NAME = "BallotStorage"; - bytes32 public constant ENV_STORAGE_NAME = "EnvStorage"; - bytes32 public constant REWARD_POOL_NAME = "RewardPool"; - bytes32 public constant MAINTENANCE_NAME = "Maintenance"; - bytes32 public constant ECOSYSTEM_NAME = "Ecosystem"; - bytes32 public constant STAKING_REWARD_NAME = "StakingReward"; - - /* - * @dev Function to set registry address. Contract that wants to use registry should setRegistry first. - * @param _addr address of registry - * @return A boolean that indicates if the operation was successful. - */ - event SetRegistry(address indexed addr); - - function setRegistry(address _addr) public onlyOwner { - require(_addr != address(0), "Address should be non-zero"); - reg = IRegistry(_addr); - emit SetRegistry(_addr); - } - - modifier onlyGov() { - require(getGovAddress() == msg.sender, "No Permission"); - _; - } - - modifier onlyGovMem() { - require(IGov(getGovAddress()).isMember(msg.sender), "No Permission"); - _; - } - - modifier onlyGovStaker() { - require(IGov(getGovAddress()).isStaker(msg.sender), "No Permission"); - _; - } - - modifier anyGov() { - require(getGovAddress() == msg.sender || IGov(getGovAddress()).isMember(msg.sender), "No Permission"); - _; - } - - function getContractAddress(bytes32 name) internal view returns (address) { - return reg.getContractAddress(name); - } - - function getGovAddress() internal view returns (address) { - return getContractAddress(GOV_NAME); - } - - function getStakingAddress() internal view returns (address) { - return getContractAddress(STAKING_NAME); - } - - function getBallotStorageAddress() internal view returns (address) { - return getContractAddress(BALLOT_STORAGE_NAME); - } - - function getEnvStorageAddress() internal view returns (address) { - return getContractAddress(ENV_STORAGE_NAME); - } - - function getRewardPoolAddress() internal view returns (address) { - return getContractAddress(REWARD_POOL_NAME); - } - - function getEcosystemAddress() internal view returns (address) { - return getContractAddress(ECOSYSTEM_NAME); - } - - function getStakingRewardAddress() internal view returns (address) { - return getContractAddress(STAKING_REWARD_NAME); - } - - function getMaintenanceAddress() internal view returns (address) { - return getContractAddress(MAINTENANCE_NAME); - } + IRegistry public reg; + + bytes32 public constant GOV_NAME = "GovernanceContract"; + bytes32 public constant STAKING_NAME = "Staking"; + bytes32 public constant BALLOT_STORAGE_NAME = "BallotStorage"; + bytes32 public constant ENV_STORAGE_NAME = "EnvStorage"; + bytes32 public constant REWARD_POOL_NAME = "RewardPool"; + bytes32 public constant MAINTENANCE_NAME = "Maintenance"; + bytes32 public constant ECOSYSTEM_NAME = "Ecosystem"; + bytes32 public constant STAKING_REWARD_NAME = "StakingReward"; + + /* + * @dev Function to set registry address. Contract that wants to use registry should setRegistry first. + * @param _addr address of registry + * @return A boolean that indicates if the operation was successful. + */ + event SetRegistry(address indexed addr); + + function setRegistry(address _addr) public onlyOwner { + require(_addr != address(0), "Address should be non-zero"); + reg = IRegistry(_addr); + emit SetRegistry(_addr); + } + + modifier onlyGov() { + require(getGovAddress() == msg.sender, "No Permission"); + _; + } + + modifier onlyGovMem() { + require(IGov(getGovAddress()).isMember(msg.sender), "No Permission"); + _; + } + + modifier onlyGovStaker() { + require(IGov(getGovAddress()).isStaker(msg.sender), "No Permission"); + _; + } + + modifier anyGov() { + require(getGovAddress() == msg.sender || IGov(getGovAddress()).isMember(msg.sender), "No Permission"); + _; + } + + function getContractAddress(bytes32 name) internal view returns (address) { + return reg.getContractAddress(name); + } + + function getGovAddress() internal view returns (address) { + return getContractAddress(GOV_NAME); + } + + function getStakingAddress() internal view returns (address) { + return getContractAddress(STAKING_NAME); + } + + function getBallotStorageAddress() internal view returns (address) { + return getContractAddress(BALLOT_STORAGE_NAME); + } + + function getEnvStorageAddress() internal view returns (address) { + return getContractAddress(ENV_STORAGE_NAME); + } + + function getRewardPoolAddress() internal view returns (address) { + return getContractAddress(REWARD_POOL_NAME); + } + + function getEcosystemAddress() internal view returns (address) { + return getContractAddress(ECOSYSTEM_NAME); + } + + function getStakingRewardAddress() internal view returns (address) { + return getContractAddress(STAKING_REWARD_NAME); + } + + function getMaintenanceAddress() internal view returns (address) { + return getContractAddress(MAINTENANCE_NAME); + } } diff --git a/wemix/governance-contract/contracts/GovImp.sol b/wemix/governance-contract/contracts/GovImp.sol index 0529c5b0ca92..ecb045c59fc3 100644 --- a/wemix/governance-contract/contracts/GovImp.sol +++ b/wemix/governance-contract/contracts/GovImp.sol @@ -12,13 +12,7 @@ import "./interface/IStaking.sol"; import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; -contract GovImp is - AGov, - ReentrancyGuardUpgradeable, - BallotEnums, - EnvConstants, - UUPSUpgradeable -{ +contract GovImp is AGov, ReentrancyGuardUpgradeable, BallotEnums, EnvConstants, UUPSUpgradeable { enum VariableTypes { Invalid, Int, @@ -36,11 +30,7 @@ contract GovImp is event MemberAdded(address indexed addr, address indexed voter); event MemberRemoved(address indexed addr, address indexed voter); - event MemberChanged( - address indexed oldAddr, - address indexed newAddr, - address indexed newVoter - ); + event MemberChanged(address indexed oldAddr, address indexed newAddr, address indexed newVoter); event EnvChanged(bytes32 envName, uint256 envType, bytes envVal); event MemberUpdated(address indexed addr, address indexed voter); // added for case that ballot's result could not be applicable. @@ -65,21 +55,13 @@ contract GovImp is modifier checkLockedAmount() { address staker = getStakerAddr(_msgSender()); - require( - lockedBalanceOf(staker) <= getMaxStaking() && - lockedBalanceOf(staker) >= getMinStaking(), - "Invalid staking balance" - ); + require(lockedBalanceOf(staker) <= getMaxStaking() && lockedBalanceOf(staker) >= getMinStaking(), "Invalid staking balance"); _; } modifier checkTimePeriod() { address staker = getStakerAddr(_msgSender()); - require( - (block.timestamp - lastAddProposalTime[staker]) >= - proposal_time_period, - "Cannot add proposal too early" - ); + require((block.timestamp - lastAddProposalTime[staker]) >= proposal_time_period, "Cannot add proposal too early"); _; lastAddProposalTime[staker] = block.timestamp; } @@ -92,11 +74,7 @@ contract GovImp is require(info.enode.length > 0, "Invalid node enode"); require(info.memo.length > 0, "Invalid memo"); require(info.duration > 0, "Invalid duration"); - require( - info.lockAmount >= getMinStaking() && - info.lockAmount <= getMaxStaking(), - "Invalid lock Amount" - ); + require(info.lockAmount >= getMinStaking() && info.lockAmount <= getMaxStaking(), "Invalid lock Amount"); _; } @@ -105,29 +83,16 @@ contract GovImp is _disableInitializers(); } - function init( - address registry, - uint256 lockAmount, - bytes memory name, - bytes memory enode, - bytes memory ip, - uint port - ) public initializer { + function init(address registry, uint256 lockAmount, bytes memory name, bytes memory enode, bytes memory ip, uint port) public initializer { __ReentrancyGuard_init(); __Ownable_init(); setRegistry(registry); - require( - lockAmount >= getMinStaking() && getMaxStaking() >= lockAmount, - "Invalid lock amount" - ); + require(lockAmount >= getMinStaking() && getMaxStaking() >= lockAmount, "Invalid lock amount"); // Lock IStaking staking = IStaking(getStakingAddress()); - require( - staking.availableBalanceOf(msg.sender) >= lockAmount, - "Insufficient staking" - ); + require(staking.availableBalanceOf(msg.sender) >= lockAmount, "Insufficient staking"); staking.lock(msg.sender, lockAmount); // Add voting member @@ -161,11 +126,7 @@ contract GovImp is emit MemberAdded(msg.sender, msg.sender); } - function initOnce( - address registry, - uint256 lockAmount, - bytes memory data - ) public initializer { + function initOnce(address registry, uint256 lockAmount, bytes memory data) public initializer { __ReentrancyGuard_init(); __Ownable_init(); setRegistry(registry); @@ -176,10 +137,7 @@ contract GovImp is // Lock IStaking staking = IStaking(getStakingAddress()); - require( - lockAmount >= getMinStaking() && getMaxStaking() >= lockAmount, - "Invalid lock amount" - ); + require(lockAmount >= getMinStaking() && getMaxStaking() >= lockAmount, "Invalid lock amount"); // []{uint staker, uint voter, uint reward, bytes name, bytes enode, bytes ip, uint port} // 32 bytes, 32 bytes, 32 bytes, [32 bytes, ] * 3, 32 bytes @@ -241,10 +199,7 @@ contract GovImp is ix += 0x20; idx += 1; - require( - !isMember(staker) && !isMember(voter) && !isReward(reward), - "Already member" - ); + require(!isMember(staker) && !isMember(voter) && !isReward(reward), "Already member"); voters[idx] = voter; voterIdx[voter] = idx; rewards[idx] = reward; @@ -253,15 +208,9 @@ contract GovImp is stakerIdx[staker] = idx; emit MemberAdded(staker, voter); // staker, voter - require( - staking.availableBalanceOf(staker) >= lockAmount, - "Insufficient staking" - ); + require(staking.availableBalanceOf(staker) >= lockAmount, "Insufficient staking"); - require( - checkNodeInfoAdd(name, enode, ip, port), - "Duplicated node info" - ); + require(checkNodeInfoAdd(name, enode, ip, port), "Duplicated node info"); lock(staker, lockAmount); @@ -285,26 +234,10 @@ contract GovImp is //Add member address = staker address = voter address function addProposalToAddMember( MemberInfo memory info - ) - external - onlyGovMem - checkTimePeriod - checkLockedAmount - checkMemberInfo(info) - returns (uint256 ballotIdx) - { - require( - !isMember(info.staker) && !isReward(info.staker), - "Already member" - ); - require( - info.staker == info.voter && info.staker == info.reward, - "Staker is not voter" - ); - require( - checkNodeInfoAdd(info.name, info.enode, info.ip, info.port), - "Duplicated node info" - ); + ) external onlyGovMem checkTimePeriod checkLockedAmount checkMemberInfo(info) returns (uint256 ballotIdx) { + require(!isMember(info.staker) && !isReward(info.staker), "Already member"); + require(info.staker == info.voter && info.staker == info.reward, "Staker is not voter"); + require(checkNodeInfoAdd(info.name, info.enode, info.ip, info.port), "Duplicated node info"); ballotIdx = ballotLength + 1; createBallotForMember( ballotIdx, // ballot id @@ -325,20 +258,11 @@ contract GovImp is uint256 duration, uint256 unlockAmount, uint256 slashing - ) - external - onlyGovMem - checkTimePeriod - checkLockedAmount - returns (uint256 ballotIdx) - { + ) external onlyGovMem checkTimePeriod checkLockedAmount returns (uint256 ballotIdx) { require(staker != ZERO, "Invalid address"); require(isMember(staker), "Non-member"); require(getMemberLength() > 1, "Cannot remove a sole member"); - require( - lockedBalanceOf(staker) >= lockAmount, - "Insufficient balance that can be unlocked." - ); + require(lockedBalanceOf(staker) >= lockAmount, "Insufficient balance that can be unlocked."); ballotIdx = ballotLength + 1; MemberInfo memory info = MemberInfo( @@ -379,14 +303,7 @@ contract GovImp is address oldStaker, uint256 unlockAmount, uint256 slashing - ) - external - onlyGovMem - checkTimePeriod - checkLockedAmount - checkMemberInfo(newInfo) - returns (uint256 ballotIdx) - { + ) external onlyGovMem checkTimePeriod checkLockedAmount checkMemberInfo(newInfo) returns (uint256 ballotIdx) { require(oldStaker != ZERO, "Invalid old Address"); require(isMember(oldStaker), "Non-member"); @@ -403,14 +320,9 @@ contract GovImp is if (msg.sender == oldStaker && oldStaker == newInfo.staker) { // Change member enviroment, finalized require(unlockAmount == 0 && slashing == 0, "Invalid proposal"); - } else if ( - oldStaker != newInfo.staker /* && msg.sender != oldStaker */ - ) { + } else if (oldStaker != newInfo.staker /* && msg.sender != oldStaker */) { // Propose Change or Exit member by other. - require( - unlockAmount + slashing <= getMinStaking(), - "Invalid amount: (unlockAmount + slashing) must be equal or low to minStaking" - ); + require(unlockAmount + slashing <= getMinStaking(), "Invalid amount: (unlockAmount + slashing) must be equal or low to minStaking"); } ballotIdx = ballotLength + 1; @@ -429,12 +341,7 @@ contract GovImp is if (msg.sender == oldStaker && oldStaker == newInfo.staker) { (, , uint256 duration) = getBallotPeriod(ballotIdx); startBallot(ballotIdx, block.timestamp, block.timestamp + duration); - finalizeVote( - ballotIdx, - uint256(BallotTypes.MemberChange), - true, - true - ); + finalizeVote(ballotIdx, uint256(BallotTypes.MemberChange), true, true); } } @@ -442,23 +349,12 @@ contract GovImp is address newGovAddr, bytes memory memo, uint256 duration - ) - external - onlyGovMem - checkTimePeriod - checkLockedAmount - returns (uint256 ballotIdx) - { + ) external onlyGovMem checkTimePeriod checkLockedAmount returns (uint256 ballotIdx) { require(newGovAddr != ZERO, "Implementation cannot be zero"); require(newGovAddr != _getImplementation(), "Same contract address"); //check newGov has proxiableUUID - try IERC1822Proxiable(newGovAddr).proxiableUUID() returns ( - bytes32 slot - ) { - require( - slot == _IMPLEMENTATION_SLOT, - "ERC1967Upgrade: unsupported proxiableUUID" - ); + try IERC1822Proxiable(newGovAddr).proxiableUUID() returns (bytes32 slot) { + require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } @@ -480,19 +376,9 @@ contract GovImp is bytes memory envVal, bytes memory memo, uint256 duration - ) - external - onlyGovMem - checkTimePeriod - checkLockedAmount - returns (uint256 ballotIdx) - { + ) external onlyGovMem checkTimePeriod checkLockedAmount returns (uint256 ballotIdx) { // require(envName != 0, "Invalid name"); - require( - uint256(VariableTypes.Int) <= envType && - envType <= uint256(VariableTypes.String), - "Invalid type" - ); + require(uint256(VariableTypes.Int) <= envType && envType <= uint256(VariableTypes.String), "Invalid type"); require(checkVariableCondition(envName, envVal), "Invalid value"); ballotIdx = ballotLength + 1; @@ -509,10 +395,7 @@ contract GovImp is ballotLength = ballotIdx; } - function vote( - uint256 ballotIdx, - bool approval - ) external nonReentrant onlyGovMem checkLockedAmount { + function vote(uint256 ballotIdx, bool approval) external nonReentrant onlyGovMem checkLockedAmount { // Check if some ballot is in progress require(checkUnfinalized(), "Expired"); @@ -523,11 +406,7 @@ contract GovImp is // Finalize (, uint256 accept, uint256 reject) = getBallotVotingInfo(ballotIdx); uint256 threshold = getThreshold(); - if ( - accept >= threshold || - reject >= threshold || - (accept + reject) == 10000 - ) { + if (accept >= threshold || reject >= threshold || (accept + reject) == 10000) { finalizeVote(ballotIdx, ballotType, accept > reject, false); } } @@ -585,31 +464,16 @@ contract GovImp is require(ballotInVoting == 0, "Now in voting with different ballot"); (, , uint256 duration) = getBallotPeriod(ballotIdx); if (duration < getMinVotingDuration()) { - startBallot( - ballotIdx, - block.timestamp, - block.timestamp + getMinVotingDuration() - ); + startBallot(ballotIdx, block.timestamp, block.timestamp + getMinVotingDuration()); } else if (getMaxVotingDuration() < duration) { - startBallot( - ballotIdx, - block.timestamp, - block.timestamp + getMaxVotingDuration() - ); + startBallot(ballotIdx, block.timestamp, block.timestamp + getMaxVotingDuration()); } else { - startBallot( - ballotIdx, - block.timestamp, - block.timestamp + duration - ); + startBallot(ballotIdx, block.timestamp, block.timestamp + duration); } ballotInVoting = ballotIdx; } else if (state == uint256(BallotStates.InProgress)) { // Nothing to do - require( - ballotIdx == ballotInVoting, - "Now in voting with different ballot" - ); + require(ballotIdx == ballotInVoting, "Now in voting with different ballot"); } else { // canceled revert("Expired"); @@ -621,25 +485,12 @@ contract GovImp is uint256 voteIdx = voteLength + 1; address staker = getStakerAddr(msg.sender); uint256 weight = 10000 / getMemberLength(); //IStaking(getStakingAddress()).calcVotingWeightWithScaleFactor(staker, 10000); - uint256 decision = approval - ? uint256(DecisionTypes.Accept) - : uint256(DecisionTypes.Reject); - IBallotStorage(getBallotStorageAddress()).createVote( - voteIdx, - ballotIdx, - staker, - decision, - weight - ); + uint256 decision = approval ? uint256(DecisionTypes.Accept) : uint256(DecisionTypes.Reject); + IBallotStorage(getBallotStorageAddress()).createVote(voteIdx, ballotIdx, staker, decision, weight); voteLength = voteIdx; } - function finalizeVote( - uint256 ballotIdx, - uint256 ballotType, - bool isAccepted, - bool self - ) private { + function finalizeVote(uint256 ballotIdx, uint256 ballotType, bool isAccepted, bool self) private { uint256 ballotState = uint256(BallotStates.Rejected); if (isAccepted) { ballotState = uint256(BallotStates.Accepted); @@ -664,20 +515,12 @@ contract GovImp is if (!self) ballotInVoting = 0; } - function fromValidBallot( - uint256 ballotIdx, - uint256 targetType - ) private view { + function fromValidBallot(uint256 ballotIdx, uint256 targetType) private view { (uint256 ballotType, uint256 state, ) = getBallotState(ballotIdx); require(ballotType == targetType, "Invalid voting type"); require(state == uint(BallotStates.InProgress), "Invalid voting state"); (, uint256 accept, uint256 reject) = getBallotVotingInfo(ballotIdx); - require( - accept >= getThreshold() || - reject >= getThreshold() || - (accept + reject) == 10000, - "Not yet finalized" - ); + require(accept >= getThreshold() || reject >= getThreshold() || (accept + reject) == 10000, "Not yet finalized"); } function addMember(uint256 ballotIdx) private returns (bool) { @@ -712,10 +555,7 @@ contract GovImp is } if (availableBalanceOf(newStaker) < lockAmount) { - emit NotApplicable( - ballotIdx, - "Insufficient balance that can be locked" - ); + emit NotApplicable(ballotIdx, "Insufficient balance that can be locked"); return false; } @@ -762,7 +602,7 @@ contract GovImp is ( address oldStaker, // newStakerAddress - // newVoterAddress + // newRewardAddress , , , @@ -771,7 +611,7 @@ contract GovImp is , , - ) = // newRewardAddress + ) = // newVoterAddress // newNodeName // newNodeId // newNodeIp @@ -789,28 +629,23 @@ contract GovImp is address oldReward = rewards[removeIdx]; if (stakerIdx[oldStaker] != memberLength) { - ( - stakers[removeIdx], + (stakers[removeIdx], stakers[memberLength], stakerIdx[oldStaker], stakerIdx[endAddr]) = ( stakers[memberLength], - stakerIdx[oldStaker], - stakerIdx[endAddr] - ) = (stakers[memberLength], ZERO, 0, stakerIdx[oldStaker]); + ZERO, + 0, + stakerIdx[oldStaker] + ); removeIdx = rewardIdx[oldStaker]; endAddr = rewards[memberLength]; - ( - rewards[removeIdx], + (rewards[removeIdx], rewards[memberLength], rewardIdx[oldReward], rewardIdx[endAddr]) = ( rewards[memberLength], - rewardIdx[oldReward], - rewardIdx[endAddr] - ) = (rewards[memberLength], ZERO, 0, rewardIdx[oldReward]); + ZERO, + 0, + rewardIdx[oldReward] + ); removeIdx = voterIdx[oldStaker]; endAddr = voters[memberLength]; - ( - voters[removeIdx], - voters[memberLength], - voterIdx[oldVoter], - voterIdx[endAddr] - ) = (voters[memberLength], ZERO, 0, voterIdx[oldVoter]); + (voters[removeIdx], voters[memberLength], voterIdx[oldVoter], voterIdx[endAddr]) = (voters[memberLength], ZERO, 0, voterIdx[oldVoter]); } else { stakers[memberLength] = ZERO; stakerIdx[oldStaker] = 0; @@ -825,9 +660,7 @@ contract GovImp is Node storage node = nodes[removeIdx]; checkNodeEnode[node.enode] = false; checkNodeName[node.name] = false; - checkNodeIpPort[ - keccak256(abi.encodePacked(node.ip, node.port)) - ] = false; + checkNodeIpPort[keccak256(abi.encodePacked(node.ip, node.port))] = false; if (nodeIdxFromMember[oldStaker] != nodeLength) { removeIdx = nodeIdxFromMember[oldStaker]; endAddr = nodeToMember[nodeLength]; @@ -877,10 +710,7 @@ contract GovImp is uint256 memberIdx = stakerIdx[oldStaker]; if (oldStaker != newStaker) { if (isMember(newStaker)) { - emit NotApplicable( - ballotIdx, - "new address is already a member" - ); + emit NotApplicable(ballotIdx, "new address is already a member"); return false; // already member. it is abnormal case. } if (newStaker != newVoter && newStaker != newReward) { @@ -893,10 +723,7 @@ contract GovImp is return false; } if (availableBalanceOf(newStaker) < lockAmount) { - emit NotApplicable( - ballotIdx, - "Insufficient balance that can be locked" - ); + emit NotApplicable(ballotIdx, "Insufficient balance that can be locked"); return false; } } @@ -917,22 +744,14 @@ contract GovImp is { address oldReward = rewards[memberIdx]; - if ( - (oldStaker != newReward) && - (oldReward != newReward) && - (isMember(newReward) || isReward(newReward)) - ) { + if ((oldStaker != newReward) && (oldReward != newReward) && (isMember(newReward) || isReward(newReward))) { emit NotApplicable(ballotIdx, "Invalid reward address"); return false; } } { address oldVoter = voters[memberIdx]; - if ( - (oldStaker != newVoter) && - (oldVoter != newVoter) && - (isMember(newVoter) || isReward(newVoter)) - ) { + if ((oldStaker != newVoter) && (oldVoter != newVoter) && (isMember(newVoter) || isReward(newVoter))) { emit NotApplicable(ballotIdx, "Invalid voters address"); return false; } @@ -964,21 +783,7 @@ contract GovImp is return false; // Non-member. it is abnormal case. } - if ( - !checkChangeMember( - ballotIdx, - self, - oldStaker, - newStaker, - newVoter, - newReward, - name, - enode, - ip, - port, - lockAmount - ) - ) return false; + if (!checkChangeMember(ballotIdx, self, oldStaker, newStaker, newVoter, newReward, name, enode, ip, port, lockAmount)) return false; //old staker uint256 memberIdx = stakerIdx[oldStaker]; @@ -997,9 +802,7 @@ contract GovImp is checkNodeName[node.name] = false; checkNodeEnode[node.enode] = false; - checkNodeIpPort[ - keccak256(abi.encodePacked(node.ip, node.port)) - ] = false; + checkNodeIpPort[keccak256(abi.encodePacked(node.ip, node.port))] = false; node.name = name; node.enode = enode; @@ -1047,8 +850,7 @@ contract GovImp is function changeGov(uint256 ballotIdx) private { fromValidBallot(ballotIdx, uint256(BallotTypes.GovernanceChange)); - address newImp = IBallotStorage(getBallotStorageAddress()) - .getBallotAddress(ballotIdx); + address newImp = IBallotStorage(getBallotStorageAddress()).getBallotAddress(ballotIdx); if (newImp != ZERO) { _authorizeUpgrade(newImp); _upgradeToAndCallUUPS(newImp, new bytes(0), false); @@ -1059,9 +861,7 @@ contract GovImp is function applyEnv(uint256 ballotIdx) private { fromValidBallot(ballotIdx, uint256(BallotTypes.EnvValChange)); - (bytes32 envKey, uint256 envType, bytes memory envVal) = IBallotStorage( - getBallotStorageAddress() - ).getBallotVariable(ballotIdx); + (bytes32 envKey, uint256 envType, bytes memory envVal) = IBallotStorage(getBallotStorageAddress()).getBallotVariable(ballotIdx); IEnvStorage envStorage = IEnvStorage(getEnvStorageAddress()); envStorage.setVariable(envKey, envVal); @@ -1071,13 +871,7 @@ contract GovImp is } //------------------ Code reduction for creation gas - function createBallotForMember( - uint256 id, - uint256 bType, - address creator, - address oAddr, - MemberInfo memory info - ) private { + function createBallotForMember(uint256 id, uint256 bType, address creator, address oAddr, MemberInfo memory info) private { IBallotStorage(getBallotStorageAddress()).createBallotForMember( id, // ballot id bType, // ballot type @@ -1095,26 +889,15 @@ contract GovImp is } function updateBallotLock(uint256 id, uint256 amount) private { - IBallotStorage(getBallotStorageAddress()).updateBallotMemberLockAmount( - id, - amount - ); + IBallotStorage(getBallotStorageAddress()).updateBallotMemberLockAmount(id, amount); } function updateBallotMemo(uint256 id, bytes memory memo) private { IBallotStorage(getBallotStorageAddress()).updateBallotMemo(id, memo); } - function createBallotForExit( - uint256 id, - uint256 unlockAmount, - uint256 slashing - ) private { - IBallotStorage(getBallotStorageAddress()).createBallotForExit( - id, - unlockAmount, - slashing - ); + function createBallotForExit(uint256 id, uint256 unlockAmount, uint256 slashing) private { + IBallotStorage(getBallotStorageAddress()).createBallotForExit(id, unlockAmount, slashing); } function startBallot(uint256 id, uint256 s, uint256 e) private { @@ -1125,47 +908,24 @@ contract GovImp is IBallotStorage(getBallotStorageAddress()).finalizeBallot(id, state); } - function getBallotState( - uint256 id - ) private view returns (uint256, uint256, bool) { + function getBallotState(uint256 id) private view returns (uint256, uint256, bool) { return IBallotStorage(getBallotStorageAddress()).getBallotState(id); } - function getBallotPeriod( - uint256 id - ) private view returns (uint256, uint256, uint256) { + function getBallotPeriod(uint256 id) private view returns (uint256, uint256, uint256) { return IBallotStorage(getBallotStorageAddress()).getBallotPeriod(id); } - function getBallotVotingInfo( - uint256 id - ) private view returns (uint256, uint256, uint256) { - return - IBallotStorage(getBallotStorageAddress()).getBallotVotingInfo(id); + function getBallotVotingInfo(uint256 id) private view returns (uint256, uint256, uint256) { + return IBallotStorage(getBallotStorageAddress()).getBallotVotingInfo(id); } function getBallotMember( uint256 id - ) - private - view - returns ( - address, - address, - address, - address, - bytes memory, - bytes memory, - bytes memory, - uint256, - uint256 - ) - { + ) private view returns (address, address, address, address, bytes memory, bytes memory, bytes memory, uint256, uint256) { return IBallotStorage(getBallotStorageAddress()).getBallotMember(id); } - function getBallotForExit( - uint256 id - ) private view returns (uint256, uint256) { + function getBallotForExit(uint256 id) private view returns (uint256, uint256) { return IBallotStorage(getBallotStorageAddress()).getBallotForExit(id); } @@ -1180,10 +940,7 @@ contract GovImp is function transferLockedAndUnlock(uint256 ballotIdx, address addr) private { (uint256 unlockAmount, uint256 slashing) = getBallotForExit(ballotIdx); - require( - unlockAmount + slashing <= getMinStaking(), - "minStaking value must be greater than or equal to the sum of unlockAmount, slashing" - ); + require(unlockAmount + slashing <= getMinStaking(), "minStaking value must be greater than or equal to the sum of unlockAmount, slashing"); IStaking staking = IStaking(getStakingAddress()); uint256 locked = staking.lockedBalanceOf(addr); @@ -1210,19 +967,10 @@ contract GovImp is //====NXTMeta=====/ - function _authorizeUpgrade( - address newImplementation - ) internal override onlyGovMem {} - - function checkVariableCondition( - bytes32 envKey, - bytes memory envVal - ) internal view returns (bool) { - return - IEnvStorage(getEnvStorageAddress()).checkVariableCondition( - envKey, - envVal - ); + function _authorizeUpgrade(address newImplementation) internal override onlyGovMem {} + + function checkVariableCondition(bytes32 envKey, bytes memory envVal) internal view returns (bool) { + return IEnvStorage(getEnvStorageAddress()).checkVariableCondition(envKey, envVal); } function getStakerAddr(address _addr) public view returns (address staker) { @@ -1236,12 +984,7 @@ contract GovImp is emit SetProposalTimePeriod(newPeriod); } - function checkNodeInfoAdd( - bytes memory name, - bytes memory enode, - bytes memory ip, - uint port - ) internal view returns (bool check) { + function checkNodeInfoAdd(bytes memory name, bytes memory enode, bytes memory ip, uint port) internal view returns (bool check) { //Enode can not be duplicated //IP:port can not be duplicated //Name can not be duplicated @@ -1264,20 +1007,11 @@ contract GovImp is //IP:port can not be duplicated //Name can not be duplicated check = true; - if ( - (keccak256(nodeInfo.enode) != keccak256(enode) && - checkNodeEnode[enode]) - ) check = false; - if ( - (keccak256(nodeInfo.name) != keccak256(name) && checkNodeName[name]) - ) check = false; + if ((keccak256(nodeInfo.enode) != keccak256(enode) && checkNodeEnode[enode])) check = false; + if ((keccak256(nodeInfo.name) != keccak256(name) && checkNodeName[name])) check = false; bytes32 hvalue = keccak256(abi.encodePacked(ip, port)); - if ( - (keccak256(abi.encodePacked(nodeInfo.ip, nodeInfo.port)) != - hvalue && - checkNodeIpPort[hvalue]) - ) check = false; + if ((keccak256(abi.encodePacked(nodeInfo.ip, nodeInfo.port)) != hvalue && checkNodeIpPort[hvalue])) check = false; } uint256 public proposal_time_period; @@ -1303,18 +1037,12 @@ contract GovImp is Node memory node = nodes[i]; checkNodeName[node.name] = true; checkNodeEnode[node.enode] = true; - checkNodeIpPort[ - keccak256(abi.encodePacked(node.ip, node.port)) - ] = true; + checkNodeIpPort[keccak256(abi.encodePacked(node.ip, node.port))] = true; } } } - function initMigration( - address registry, - uint256 oldModifiedBlock, - address oldOwner - ) external override initializer { + function initMigration(address registry, uint256 oldModifiedBlock, address oldOwner) external override initializer { __ReentrancyGuard_init(); __Ownable_init(); setRegistry(registry); @@ -1324,9 +1052,7 @@ contract GovImp is emit GovDataMigrated(msg.sender); } - function migrateFromLegacy( - address oldGov - ) external initializer returns (int256) { + function migrateFromLegacy(address oldGov) external initializer returns (int256) { __ReentrancyGuard_init(); __Ownable_init(); @@ -1347,28 +1073,15 @@ contract GovImp is Node memory node; (node.name, node.enode, node.ip, node.port) = ogov.getNode(i); - require( - checkNodeInfoChange( - node.name, - node.enode, - node.ip, - node.port, - node - ), - "node info is duplicated" - ); + require(checkNodeInfoChange(node.name, node.enode, node.ip, node.port, node), "node info is duplicated"); checkNodeName[node.name] = true; checkNodeEnode[node.enode] = true; - checkNodeIpPort[ - keccak256(abi.encodePacked(node.ip, node.port)) - ] = true; + checkNodeIpPort[keccak256(abi.encodePacked(node.ip, node.port))] = true; nodes[i] = node; nodeIdxFromMember[stakers[i]] = i; nodeToMember[i] = stakers[i]; nodeLength = i; - lastAddProposalTime[stakers[i]] = ogov.lastAddProposalTime( - stakers[i] - ); + lastAddProposalTime[stakers[i]] = ogov.lastAddProposalTime(stakers[i]); } } diff --git a/wemix/governance-contract/contracts/NCPExit.sol b/wemix/governance-contract/contracts/NCPExit.sol index 46bf150c2800..5d92b4efc29f 100644 --- a/wemix/governance-contract/contracts/NCPExit.sol +++ b/wemix/governance-contract/contracts/NCPExit.sol @@ -5,9 +5,9 @@ import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "@openzeppelin/contracts/proxy/beacon/IBeacon.sol"; contract NCPExit is ERC1967Proxy, IBeacon { - constructor(address _imp) ERC1967Proxy(_imp, "") {} + constructor(address _imp) ERC1967Proxy(_imp, "") {} - function implementation() external view override returns (address) { - return _implementation(); - } + function implementation() external view override returns (address) { + return _implementation(); + } } diff --git a/wemix/governance-contract/contracts/NCPExitImp.sol b/wemix/governance-contract/contracts/NCPExitImp.sol index 5e43460178b7..be01d3ab871a 100644 --- a/wemix/governance-contract/contracts/NCPExitImp.sol +++ b/wemix/governance-contract/contracts/NCPExitImp.sol @@ -11,105 +11,105 @@ import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; contract NCPExitImp is GovChecker, INCPExit, UUPSUpgradeable, ReentrancyGuardUpgradeable { - /* =========== STATE VARIABLES ===========*/ - using AddressUpgradeable for address payable; - - address private _administrator; - address private _administratorSetter; - - mapping(address /* ncp address */ => /* user + a */ uint256) private _receivedTotalAmount; - mapping(address /* ncp address */ => /* user */ uint256) private _lockedUserBalanceToNCPTotal; - - /* =========== MODIFIERES ===========*/ - modifier onlyGovStaking() { - require(msg.sender == getStakingAddress(), "Only governance staking contract can call this function."); - _; - } - - modifier onlyNcpStaking() { - require(msg.sender == IGovStaking(getStakingAddress()).ncpStaking(), "Only NcpStaking can call this function."); - _; - } - - modifier onlyAdministrator() { - require(msg.sender == _administrator, "Only Administrator can call this function."); - _; - } - - modifier onlyAdministratorSetter() { - require(msg.sender == _administratorSetter, "Caller is not AdministratorSetter."); - _; - } - - receive() external payable {} - - /* =========== FUNCTIONS ===========*/ - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - _disableInitializers(); - } - function initialize(address _registry) external initializer { - __Ownable_init(); - __ReentrancyGuard_init(); - setRegistry(_registry); - _administrator = owner(); - _administratorSetter = owner(); - } - - function setAdministrator(address _newAdministrator) external override onlyAdministratorSetter { - require(_newAdministrator != address(0), "Address should be non-zero"); - _administrator = _newAdministrator; - } - - function setAdministratorSetter(address _newAdministratorSetter) external override onlyAdministratorSetter { - require(_newAdministratorSetter != address(0), "Address should be non-zero"); - _administratorSetter = _newAdministratorSetter; - } - - function depositExitAmount( - address exitNcp, - uint256 totalAmount, - uint256 lockedUserBalanceToNCPTotal - ) external payable override nonReentrant onlyGovStaking { - require(totalAmount == msg.value); - _receivedTotalAmount[exitNcp] = totalAmount; - - // administrator - _lockedUserBalanceToNCPTotal[exitNcp] = lockedUserBalanceToNCPTotal; - } - - function withdrawForUser(address exitNcp, address exitUser, uint256 amount) external override nonReentrant onlyNcpStaking { - require(_lockedUserBalanceToNCPTotal[exitNcp] >= amount, "_lockedUserBalanceToNCPTotal[exitNcp] >= amount"); - - _receivedTotalAmount[exitNcp] = _receivedTotalAmount[exitNcp] - amount; - _lockedUserBalanceToNCPTotal[exitNcp] = _lockedUserBalanceToNCPTotal[exitNcp] - amount; - - payable(exitUser).sendValue(amount); - } - - function withdrawForAdministrator(address exitNcp, uint256 amount, address to) external override nonReentrant onlyAdministrator { - // For admin - require(_receivedTotalAmount[exitNcp] - _lockedUserBalanceToNCPTotal[exitNcp] >= amount); - _receivedTotalAmount[exitNcp] = _receivedTotalAmount[exitNcp] - amount; - - payable(to).sendValue(amount); - } - - function getAvailableAmountForAdministrator(address exitNcp) external view override onlyAdministrator returns (uint256) { - // For admin - return _receivedTotalAmount[exitNcp] - _lockedUserBalanceToNCPTotal[exitNcp]; - } - - function upgradeNCPExit(address newImp) external onlyOwner { - if (newImp != address(0)) { - _authorizeUpgrade(newImp); - _upgradeToAndCallUUPS(newImp, new bytes(0), false); - } - } - - function getLockedUserBalanceToNCPTotal(address exitNcp) external view override returns (uint256) { - return _lockedUserBalanceToNCPTotal[exitNcp]; - } - - function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} + /* =========== STATE VARIABLES ===========*/ + using AddressUpgradeable for address payable; + + address private _administrator; + address private _administratorSetter; + + mapping(address /* ncp address */ => /* user + a */ uint256) private _receivedTotalAmount; + mapping(address /* ncp address */ => /* user */ uint256) private _lockedUserBalanceToNCPTotal; + + /* =========== MODIFIERES ===========*/ + modifier onlyGovStaking() { + require(msg.sender == getStakingAddress(), "Only governance staking contract can call this function."); + _; + } + + modifier onlyNcpStaking() { + require(msg.sender == IGovStaking(getStakingAddress()).ncpStaking(), "Only NcpStaking can call this function."); + _; + } + + modifier onlyAdministrator() { + require(msg.sender == _administrator, "Only Administrator can call this function."); + _; + } + + modifier onlyAdministratorSetter() { + require(msg.sender == _administratorSetter, "Caller is not AdministratorSetter."); + _; + } + + receive() external payable {} + + /* =========== FUNCTIONS ===========*/ + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + function initialize(address _registry) external initializer { + __Ownable_init(); + __ReentrancyGuard_init(); + setRegistry(_registry); + _administrator = owner(); + _administratorSetter = owner(); + } + + function setAdministrator(address _newAdministrator) external override onlyAdministratorSetter { + require(_newAdministrator != address(0), "Address should be non-zero"); + _administrator = _newAdministrator; + } + + function setAdministratorSetter(address _newAdministratorSetter) external override onlyAdministratorSetter { + require(_newAdministratorSetter != address(0), "Address should be non-zero"); + _administratorSetter = _newAdministratorSetter; + } + + function depositExitAmount( + address exitNcp, + uint256 totalAmount, + uint256 lockedUserBalanceToNCPTotal + ) external payable override nonReentrant onlyGovStaking { + require(totalAmount == msg.value); + _receivedTotalAmount[exitNcp] = totalAmount; + + // administrator + _lockedUserBalanceToNCPTotal[exitNcp] = lockedUserBalanceToNCPTotal; + } + + function withdrawForUser(address exitNcp, address exitUser, uint256 amount) external override nonReentrant onlyNcpStaking { + require(_lockedUserBalanceToNCPTotal[exitNcp] >= amount, "_lockedUserBalanceToNCPTotal[exitNcp] >= amount"); + + _receivedTotalAmount[exitNcp] = _receivedTotalAmount[exitNcp] - amount; + _lockedUserBalanceToNCPTotal[exitNcp] = _lockedUserBalanceToNCPTotal[exitNcp] - amount; + + payable(exitUser).sendValue(amount); + } + + function withdrawForAdministrator(address exitNcp, uint256 amount, address to) external override nonReentrant onlyAdministrator { + // For admin + require(_receivedTotalAmount[exitNcp] - _lockedUserBalanceToNCPTotal[exitNcp] >= amount); + _receivedTotalAmount[exitNcp] = _receivedTotalAmount[exitNcp] - amount; + + payable(to).sendValue(amount); + } + + function getAvailableAmountForAdministrator(address exitNcp) external view override onlyAdministrator returns (uint256) { + // For admin + return _receivedTotalAmount[exitNcp] - _lockedUserBalanceToNCPTotal[exitNcp]; + } + + function upgradeNCPExit(address newImp) external onlyOwner { + if (newImp != address(0)) { + _authorizeUpgrade(newImp); + _upgradeToAndCallUUPS(newImp, new bytes(0), false); + } + } + + function getLockedUserBalanceToNCPTotal(address exitNcp) external view override returns (uint256) { + return _lockedUserBalanceToNCPTotal[exitNcp]; + } + + function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} } diff --git a/wemix/governance-contract/contracts/Registry.sol b/wemix/governance-contract/contracts/Registry.sol index 703e550b7f00..7cc0ea380de3 100644 --- a/wemix/governance-contract/contracts/Registry.sol +++ b/wemix/governance-contract/contracts/Registry.sol @@ -12,71 +12,71 @@ import "./interface/IRegistry.sol"; * Owner should set domain and permission. */ contract Registry is Ownable, IRegistry { - // "Wemix Registry" - uint public magic = 0x57656d6978205265676973747279; - uint public modifiedBlock; + // "Wemix Registry" + uint public magic = 0x57656d6978205265676973747279; + uint public modifiedBlock; - mapping(bytes32 => address) public contracts; - mapping(bytes32 => mapping(address => bool)) public permissions; + mapping(bytes32 => address) public contracts; + mapping(bytes32 => mapping(address => bool)) public permissions; - event SetContractDomain(address setter, bytes32 indexed name, address indexed addr); - event SetPermission(bytes32 indexed _contract, address indexed granted, bool status); + event SetContractDomain(address setter, bytes32 indexed name, address indexed addr); + event SetPermission(bytes32 indexed _contract, address indexed granted, bool status); - constructor() Ownable() {} + constructor() Ownable() {} - /* - * @dev Function to set contract(can be general address) domain - * Only owner can use this function - * @param _name name - * @param _addr address - * @return A boolean that indicates if the operation was successful. - */ - function setContractDomain(bytes32 _name, address _addr) public onlyOwner returns (bool success) { - require(_addr != address(0x0), "address should be non-zero"); - contracts[_name] = _addr; - modifiedBlock = block.number; + /* + * @dev Function to set contract(can be general address) domain + * Only owner can use this function + * @param _name name + * @param _addr address + * @return A boolean that indicates if the operation was successful. + */ + function setContractDomain(bytes32 _name, address _addr) public onlyOwner returns (bool success) { + require(_addr != address(0x0), "address should be non-zero"); + contracts[_name] = _addr; + modifiedBlock = block.number; - emit SetContractDomain(msg.sender, _name, _addr); - return true; - } + emit SetContractDomain(msg.sender, _name, _addr); + return true; + } - /* - * @dev Function to get contract(can be general address) address - * Anyone can use this function - * @param _name _name - * @return An address of the _name - */ - function getContractAddress(bytes32 _name) public view override returns (address addr) { - require(contracts[_name] != address(0x0), "address should be non-zero"); - return contracts[_name]; - } + /* + * @dev Function to get contract(can be general address) address + * Anyone can use this function + * @param _name _name + * @return An address of the _name + */ + function getContractAddress(bytes32 _name) public view override returns (address addr) { + require(contracts[_name] != address(0x0), "address should be non-zero"); + return contracts[_name]; + } - /* - * @dev Function to set permission on contract - * using modifier 'permissioned' references mapping variable 'permissions' - * Only owner can use this function - * @param _contract contract name - * @param _granted granted address - * @param _status true = can use, false = cannot use. default is false - * @return A boolean that indicates if the operation was successful. - */ - function setPermission(bytes32 _contract, address _granted, bool _status) public onlyOwner returns (bool success) { - require(_granted != address(0x0), "address should be non-zero"); - permissions[_contract][_granted] = _status; - modifiedBlock = block.number; + /* + * @dev Function to set permission on contract + * using modifier 'permissioned' references mapping variable 'permissions' + * Only owner can use this function + * @param _contract contract name + * @param _granted granted address + * @param _status true = can use, false = cannot use. default is false + * @return A boolean that indicates if the operation was successful. + */ + function setPermission(bytes32 _contract, address _granted, bool _status) public onlyOwner returns (bool success) { + require(_granted != address(0x0), "address should be non-zero"); + permissions[_contract][_granted] = _status; + modifiedBlock = block.number; - emit SetPermission(_contract, _granted, _status); - return true; - } + emit SetPermission(_contract, _granted, _status); + return true; + } - /* - * @dev Function to get permission on contract - * using modifier 'permissioned' references mapping variable 'permissions' - * @param _contract contract name - * @param _granted granted address - * @return permission result - */ - function getPermission(bytes32 _contract, address _granted) public view returns (bool found) { - return permissions[_contract][_granted]; - } + /* + * @dev Function to get permission on contract + * using modifier 'permissioned' references mapping variable 'permissions' + * @param _contract contract name + * @param _granted granted address + * @return permission result + */ + function getPermission(bytes32 _contract, address _granted) public view returns (bool found) { + return permissions[_contract][_granted]; + } } diff --git a/wemix/governance-contract/contracts/StakingImp.sol b/wemix/governance-contract/contracts/StakingImp.sol index 1b99f0209dd9..a56c64646f59 100644 --- a/wemix/governance-contract/contracts/StakingImp.sol +++ b/wemix/governance-contract/contracts/StakingImp.sol @@ -12,374 +12,374 @@ import "./interface/INCPStaking.sol"; import "./interface/INCPExit.sol"; contract StakingImp is GovChecker, UUPSUpgradeable, ReentrancyGuardUpgradeable, IStaking { - //balance of each NCP - mapping(address => uint256) private _balance; - mapping(address => uint256) private _lockedBalance; - uint256 private _totalLockedBalance; - bool private revoked; - - //====NXTMeta====// - event Staked(address indexed payee, uint256 amount, uint256 total, uint256 available); - event Unstaked(address indexed payee, uint256 amount, uint256 total, uint256 available); - event Locked(address indexed payee, uint256 amount, uint256 total, uint256 available); - event Unlocked(address indexed payee, uint256 amount, uint256 total, uint256 available); - event TransferLocked(address indexed payee, uint256 amount, uint256 total, uint256 available); - event Revoked(address indexed owner, uint256 amount); - - //====Phase2-Staking====// - event DelegateStaked(address indexed payee, uint256 amount, address indexed ncp, uint256 ncpTotalLocked, uint256 userTotalLocked); - event DelegateUnstaked(address indexed payee, uint256 amount, address indexed ncp, uint256 ncpTotalLocked, uint256 userTotalLocked); - event NCPAddrChanged(address indexed ncp); - - constructor() { - _disableInitializers(); - } - - function init(address registry, bytes memory data) external initializer { - _totalLockedBalance = 0; - revoked = false; - // _transferOwnership(_msgSender()); - __ReentrancyGuard_init(); - __Ownable_init(); - setRegistry(registry); - - // data is only for test purpose - if (data.length == 0) return; - - // []{address, amount} - address addr; - uint amount; - uint ix; - uint eix; - assembly { - ix := add(data, 0x20) - } - eix = ix + data.length; - while (ix < eix) { - assembly { - addr := mload(ix) - } - ix += 0x20; - require(ix < eix); - assembly { - amount := mload(ix) - } - ix += 0x20; - - _balance[addr] = amount; - } - } - - receive() external payable { - revert(); - } - - /** - * @dev Deposit from a sender. - */ - function deposit() external payable override nonReentrant notRevoked { - require(msg.value > 0, "Deposit amount should be greater than zero"); - - _balance[msg.sender] = _balance[msg.sender] + msg.value; - - if (IGov(getGovAddress()).isMember(msg.sender)) { - uint256 minimum_staking = IEnvStorage(getEnvStorageAddress()).getStakingMin(); - //if minimum lock is going higher than current locked value, lock more - if (minimum_staking > _lockedBalance[msg.sender] && availableBalanceOf(msg.sender) >= (minimum_staking - _lockedBalance[msg.sender])) { - if (ncpStaking != address(0)) { - uint256 pid = INCPStaking(ncpStaking).ncpToIdx(msg.sender); - if (INCPStaking(ncpStaking).getUserInfo(pid, msg.sender).lastRewardClaimed != 0) { - INCPStaking(ncpStaking).ncpDeposit(minimum_staking - _lockedBalance[msg.sender], payable(msg.sender)); - } - } - _lock(msg.sender, minimum_staking - _lockedBalance[msg.sender]); - } - } - - emit Staked(msg.sender, msg.value, _balance[msg.sender], availableBalanceOf(msg.sender)); - } - - /** - * @dev Withdraw for a sender. - * @param amount The amount of funds will be withdrawn and transferred to. - */ - function withdraw(uint256 amount) external override nonReentrant notRevoked { - require(amount > 0, "Amount should be bigger than zero"); - - //if minimum is changed unlock staked value - uint256 minimum_staking = IEnvStorage(getEnvStorageAddress()).getStakingMin(); - - bool unlockBalance = false; - if (lockedBalanceOf(msg.sender) - _lockedUserBalanceToNCPTotal[msg.sender] >= minimum_staking + amount) { - _unlock(msg.sender, amount); - unlockBalance = true; - } - - require(amount <= availableBalanceOf(msg.sender), "Withdraw amount should be equal or less than balance"); - - _balance[msg.sender] = _balance[msg.sender] - amount; - - if (ncpStaking != address(0) && unlockBalance) { - (bool succ, ) = payable(ncpStaking).call{ value: amount }(""); - require(succ, "Transfer to NCP staking failed"); - INCPStaking(ncpStaking).ncpWithdraw(amount, payable(msg.sender)); - } else { - //payable(msg.sender).transfer(amount); - (bool succ, ) = payable(msg.sender).call{ value: amount }(""); - require(succ, "Transfer to sender failed"); - } - - emit Unstaked(msg.sender, amount, _balance[msg.sender], availableBalanceOf(msg.sender)); - } - - /** - * @dev Lock fund - * @param payee The address whose funds will be locked. - * @param lockAmount The amount of funds will be locked. - */ - function lock(address payee, uint256 lockAmount) external override onlyGov { - _lock(payee, lockAmount); - } - - function lockMore(uint256 lockAmount) external onlyGovStaker { - _lock(msg.sender, lockAmount); - - if (ncpStaking != address(0)) { - uint256 pid = INCPStaking(ncpStaking).ncpToIdx(msg.sender); - if (INCPStaking(ncpStaking).getUserInfo(pid, msg.sender).lastRewardClaimed != 0) { - INCPStaking(ncpStaking).ncpDeposit(lockAmount, payable(msg.sender)); - } - } - } - - function _lock(address payee, uint256 lockAmount) internal { - if (lockAmount == 0) return; - require(_balance[payee] >= lockAmount, "Lock amount should be equal or less than balance"); - require(availableBalanceOf(payee) >= lockAmount, "Insufficient balance that can be locked"); - uint256 maximum = IEnvStorage(getEnvStorageAddress()).getStakingMax(); - - _lockedBalance[payee] = _lockedBalance[payee] + lockAmount; - require(_lockedBalance[payee] <= maximum, "Locked balance is larger than max"); - - _totalLockedBalance = _totalLockedBalance + lockAmount; - - emit Locked(payee, lockAmount, _balance[payee], availableBalanceOf(payee)); - } - - /** - * @dev Transfer locked value(slashing, ncpLockMore, ncpUserTotal) to Ecosystem, NCPExit - * @param from The address whose funds will be transfered. - * @param slashing The amount of funds will be transfered. - * @param ext ncpLockMore + ncpUserTotal - */ - function transferLocked(address from, uint256 slashing, uint256 ext) external override onlyGov { - INCPExit ncpExit = INCPExit(getContractAddress(bytes32("NCPExit"))); - - // Ecosystem - unlock(from, slashing); - _balance[from] = _balance[from] - slashing; - address ecosystem = getEcosystemAddress(); - _balance[ecosystem] = _balance[ecosystem] + slashing; - - // NCPLockMore - uint256 ncpLockMore = ext - _lockedUserBalanceToNCPTotal[from]; - unlock(from, ncpLockMore); - - // To NCPExit - uint256 transferedBalance = lockedBalanceOf(from); - require( - transferedBalance >= _lockedUserBalanceToNCPTotal[from], - "transferedBalance must be greater than or equal to _lockedUserBalanceToNCPTotal." - ); - - unlock(from, transferedBalance); - _balance[from] = _balance[from] - transferedBalance; - ncpExit.depositExitAmount{ value: transferedBalance }(from, transferedBalance, _lockedUserBalanceToNCPTotal[from]); - if (ncpStaking != address(0)) { - _lockedUserBalanceToNCPTotal[from] = 0; - _lockedUserBalanceToNCP[from][ncpStaking] = 0; - } - emit TransferLocked(from, slashing + transferedBalance, _balance[from], availableBalanceOf(from)); - } - - /** - * @dev Unlock fund - * @param payee The address whose funds will be unlocked. - * @param unlockAmount The amount of funds will be unlocked. - */ - function unlock(address payee, uint256 unlockAmount) public override onlyGov { - _unlock(payee, unlockAmount); - } - - function _unlock(address payee, uint256 unlockAmount) internal { - if (unlockAmount == 0) return; - require(_lockedBalance[payee] >= unlockAmount, "Unlock amount should be equal or less than balance locked"); - _lockedBalance[payee] = _lockedBalance[payee] - unlockAmount; - _totalLockedBalance = _totalLockedBalance - unlockAmount; - - emit Unlocked(payee, unlockAmount, _balance[payee], availableBalanceOf(payee)); - } - - function balanceOf(address payee) public view override returns (uint256) { - return _balance[payee]; - } - - function lockedBalanceOf(address payee) public view override returns (uint256) { - return _lockedBalance[payee]; - } - - function availableBalanceOf(address payee) public view override returns (uint256) { - return _balance[payee] - _lockedBalance[payee]; - } - - /** - * @dev Calculate voting weight which range between 0 and 100. - * @param payee The address whose funds were locked. - */ - function calcVotingWeight(address payee) public view override returns (uint256) { - return calcVotingWeightWithScaleFactor(payee, 1e2); - } - - /** - * @dev Calculate voting weight with a scale factor. - * @param payee The address whose funds were locked. - * @param factor The scale factor for weight. For instance: - * if 1e1, result range is between 0 ~ 10 - * if 1e2, result range is between 0 ~ 100 - * if 1e3, result range is between 0 ~ 1000 - */ - function calcVotingWeightWithScaleFactor(address payee, uint32 factor) public view override returns (uint256) { - if (_lockedBalance[payee] == 0 || factor == 0) return 0; - return (_lockedBalance[payee] * factor) / _totalLockedBalance; - } - - function isRevoked() public view returns (bool) { - return revoked; - } - - modifier notRevoked() { - require(!revoked, "Is revoked"); - _; - } - - /** - * @dev Allows the owner to revoke the staking. Funds already staked are returned to the owner - */ - function revoke() public onlyOwner notRevoked { - address contractOwner = owner(); - uint256 balance = address(this).balance; - - require(balance > 0, "balance = 0"); - - payable(contractOwner).transfer(balance); - revoked = true; - - emit Revoked(contractOwner, balance); - } - - function upgradeStaking(address newImp) external onlyOwner { - if (newImp != address(0)) { - _authorizeUpgrade(newImp); - _upgradeToAndCallUUPS(newImp, new bytes(0), false); - } - } - - function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - */ - uint256[49] private __gap; - - //Phase2 - Staking - mapping(address /* NCP */ => mapping(address /* user */ => uint256 /* amount */)) private _lockedUserBalanceToNCP; - mapping(address /* NCP */ => uint256 /* amount */) private _lockedUserBalanceToNCPTotal; - - address public ncpStaking; - - modifier onlyNCPStaking() { - require(msg.sender == ncpStaking, "Only NCPStaking contract can call this function"); - _; - } - - function userBalanceOf(address ncp, address user) external view override returns (uint256) { - return _lockedUserBalanceToNCP[ncp][user]; - } - - function userTotalBalanceOf(address ncp) external view override returns (uint256) { - return _lockedUserBalanceToNCPTotal[ncp]; - } - - function getRatioOfUserBalance(address ncp) external view override returns (uint256) { - uint256 user = _lockedUserBalanceToNCPTotal[ncp]; - uint256 locked = _lockedBalance[ncp]; - if (user == 0 || locked == 0) return 0; - return (user * 1e2) / locked; - } - - function setNCPStaking(address _ncpStaking) external onlyOwner { - require(_ncpStaking != address(0), "NCPStaking is the zero address"); - ncpStaking = _ncpStaking; - emit NCPAddrChanged(_ncpStaking); - } - - /** - * @dev Deposit from a user for delegate staking. - */ - function delegateDepositAndLockMore(address ncp) external payable override nonReentrant notRevoked onlyNCPStaking { - require(msg.value > 0, "Deposit amount should be greater than zero"); - require(IGov(getGovAddress()).isMember(ncp), "NCP should be a member"); - - // console.log("delegateDepositAndLockMore: msg.value: %s",ncp); - - uint256 userDepositValue = msg.value; - //added value to ncp balance - _balance[ncp] = _balance[ncp] + userDepositValue; - - uint256 minimum_staking = IEnvStorage(getEnvStorageAddress()).getStakingMin(); - uint256 maximum_staking = IEnvStorage(getEnvStorageAddress()).getStakingMax(); - require( - minimum_staking <= _lockedBalance[ncp] && (_lockedBalance[ncp] + userDepositValue) <= maximum_staking, - "user should be in staking range" - ); - _lock(ncp, userDepositValue); - - _lockedUserBalanceToNCP[ncp][msg.sender] = _lockedUserBalanceToNCP[ncp][msg.sender] + userDepositValue; - _lockedUserBalanceToNCPTotal[ncp] = _lockedUserBalanceToNCPTotal[ncp] + userDepositValue; - - emit DelegateStaked(msg.sender, userDepositValue, ncp, _lockedUserBalanceToNCPTotal[ncp], _lockedUserBalanceToNCP[ncp][msg.sender]); - } - - /** - * @dev Withdraw for a user. - * @param amount The amount of funds will be unlocked, withdrawn and transferred to. - */ - function delegateUnlockAndWithdraw(address ncp, uint256 amount) external override nonReentrant notRevoked onlyNCPStaking { - require(amount > 0, "Amount should be bigger than zero"); - require(IGov(getGovAddress()).isMember(ncp), "NCP should be a member"); - - uint256 userWithdrawValue = amount; - uint256 minimum_staking = IEnvStorage(getEnvStorageAddress()).getStakingMin(); - require( - userWithdrawValue <= _lockedUserBalanceToNCP[ncp][msg.sender] && lockedBalanceOf(ncp) - userWithdrawValue >= minimum_staking, - "Withdraw amount should be equal or less than balance" - ); - _unlock(ncp, userWithdrawValue); - - _balance[ncp] = _balance[ncp] - userWithdrawValue; - _lockedUserBalanceToNCP[ncp][msg.sender] = _lockedUserBalanceToNCP[ncp][msg.sender] - userWithdrawValue; - _lockedUserBalanceToNCPTotal[ncp] = _lockedUserBalanceToNCPTotal[ncp] - userWithdrawValue; - - // payable(ncpStaking).transfer(userWithdrawValue); - (bool succ, ) = payable(ncpStaking).call{ value: userWithdrawValue }(""); - require(succ, "Transfer to NCP staking failed"); - - emit DelegateUnstaked(msg.sender, userWithdrawValue, ncp, _lockedUserBalanceToNCPTotal[ncp], _lockedUserBalanceToNCP[ncp][msg.sender]); - } - - function getTotalLockedBalance() external view override returns (uint256) { - return _totalLockedBalance; - } + //balance of each NCP + mapping(address => uint256) private _balance; + mapping(address => uint256) private _lockedBalance; + uint256 private _totalLockedBalance; + bool private revoked; + + //====NXTMeta====// + event Staked(address indexed payee, uint256 amount, uint256 total, uint256 available); + event Unstaked(address indexed payee, uint256 amount, uint256 total, uint256 available); + event Locked(address indexed payee, uint256 amount, uint256 total, uint256 available); + event Unlocked(address indexed payee, uint256 amount, uint256 total, uint256 available); + event TransferLocked(address indexed payee, uint256 amount, uint256 total, uint256 available); + event Revoked(address indexed owner, uint256 amount); + + //====Phase2-Staking====// + event DelegateStaked(address indexed payee, uint256 amount, address indexed ncp, uint256 ncpTotalLocked, uint256 userTotalLocked); + event DelegateUnstaked(address indexed payee, uint256 amount, address indexed ncp, uint256 ncpTotalLocked, uint256 userTotalLocked); + event NCPAddrChanged(address indexed ncp); + + constructor() { + _disableInitializers(); + } + + function init(address registry, bytes memory data) external initializer { + _totalLockedBalance = 0; + revoked = false; + // _transferOwnership(_msgSender()); + __ReentrancyGuard_init(); + __Ownable_init(); + setRegistry(registry); + + // data is only for test purpose + if (data.length == 0) return; + + // []{address, amount} + address addr; + uint amount; + uint ix; + uint eix; + assembly { + ix := add(data, 0x20) + } + eix = ix + data.length; + while (ix < eix) { + assembly { + addr := mload(ix) + } + ix += 0x20; + require(ix < eix); + assembly { + amount := mload(ix) + } + ix += 0x20; + + _balance[addr] = amount; + } + } + + receive() external payable { + revert(); + } + + /** + * @dev Deposit from a sender. + */ + function deposit() external payable override nonReentrant notRevoked { + require(msg.value > 0, "Deposit amount should be greater than zero"); + + _balance[msg.sender] = _balance[msg.sender] + msg.value; + + if (IGov(getGovAddress()).isMember(msg.sender)) { + uint256 minimum_staking = IEnvStorage(getEnvStorageAddress()).getStakingMin(); + //if minimum lock is going higher than current locked value, lock more + if (minimum_staking > _lockedBalance[msg.sender] && availableBalanceOf(msg.sender) >= (minimum_staking - _lockedBalance[msg.sender])) { + if (ncpStaking != address(0)) { + uint256 pid = INCPStaking(ncpStaking).ncpToIdx(msg.sender); + if (INCPStaking(ncpStaking).getUserInfo(pid, msg.sender).lastRewardClaimed != 0) { + INCPStaking(ncpStaking).ncpDeposit(minimum_staking - _lockedBalance[msg.sender], payable(msg.sender)); + } + } + _lock(msg.sender, minimum_staking - _lockedBalance[msg.sender]); + } + } + + emit Staked(msg.sender, msg.value, _balance[msg.sender], availableBalanceOf(msg.sender)); + } + + /** + * @dev Withdraw for a sender. + * @param amount The amount of funds will be withdrawn and transferred to. + */ + function withdraw(uint256 amount) external override nonReentrant notRevoked { + require(amount > 0, "Amount should be bigger than zero"); + + //if minimum is changed unlock staked value + uint256 minimum_staking = IEnvStorage(getEnvStorageAddress()).getStakingMin(); + + bool unlockBalance = false; + if (lockedBalanceOf(msg.sender) - _lockedUserBalanceToNCPTotal[msg.sender] >= minimum_staking + amount) { + _unlock(msg.sender, amount); + unlockBalance = true; + } + + require(amount <= availableBalanceOf(msg.sender), "Withdraw amount should be equal or less than balance"); + + _balance[msg.sender] = _balance[msg.sender] - amount; + + if (ncpStaking != address(0) && unlockBalance) { + (bool succ, ) = payable(ncpStaking).call{ value: amount }(""); + require(succ, "Transfer to NCP staking failed"); + INCPStaking(ncpStaking).ncpWithdraw(amount, payable(msg.sender)); + } else { + //payable(msg.sender).transfer(amount); + (bool succ, ) = payable(msg.sender).call{ value: amount }(""); + require(succ, "Transfer to sender failed"); + } + + emit Unstaked(msg.sender, amount, _balance[msg.sender], availableBalanceOf(msg.sender)); + } + + /** + * @dev Lock fund + * @param payee The address whose funds will be locked. + * @param lockAmount The amount of funds will be locked. + */ + function lock(address payee, uint256 lockAmount) external override onlyGov { + _lock(payee, lockAmount); + } + + function lockMore(uint256 lockAmount) external onlyGovStaker { + _lock(msg.sender, lockAmount); + + if (ncpStaking != address(0)) { + uint256 pid = INCPStaking(ncpStaking).ncpToIdx(msg.sender); + if (INCPStaking(ncpStaking).getUserInfo(pid, msg.sender).lastRewardClaimed != 0) { + INCPStaking(ncpStaking).ncpDeposit(lockAmount, payable(msg.sender)); + } + } + } + + function _lock(address payee, uint256 lockAmount) internal { + if (lockAmount == 0) return; + require(_balance[payee] >= lockAmount, "Lock amount should be equal or less than balance"); + require(availableBalanceOf(payee) >= lockAmount, "Insufficient balance that can be locked"); + uint256 maximum = IEnvStorage(getEnvStorageAddress()).getStakingMax(); + + _lockedBalance[payee] = _lockedBalance[payee] + lockAmount; + require(_lockedBalance[payee] <= maximum, "Locked balance is larger than max"); + + _totalLockedBalance = _totalLockedBalance + lockAmount; + + emit Locked(payee, lockAmount, _balance[payee], availableBalanceOf(payee)); + } + + /** + * @dev Transfer locked value(slashing, ncpLockMore, ncpUserTotal) to Ecosystem, NCPExit + * @param from The address whose funds will be transfered. + * @param slashing The amount of funds will be transfered. + * @param ext ncpLockMore + ncpUserTotal + */ + function transferLocked(address from, uint256 slashing, uint256 ext) external override onlyGov { + INCPExit ncpExit = INCPExit(getContractAddress(bytes32("NCPExit"))); + + // Ecosystem + unlock(from, slashing); + _balance[from] = _balance[from] - slashing; + address ecosystem = getEcosystemAddress(); + _balance[ecosystem] = _balance[ecosystem] + slashing; + + // NCPLockMore + uint256 ncpLockMore = ext - _lockedUserBalanceToNCPTotal[from]; + unlock(from, ncpLockMore); + + // To NCPExit + uint256 transferedBalance = lockedBalanceOf(from); + require( + transferedBalance >= _lockedUserBalanceToNCPTotal[from], + "transferedBalance must be greater than or equal to _lockedUserBalanceToNCPTotal." + ); + + unlock(from, transferedBalance); + _balance[from] = _balance[from] - transferedBalance; + ncpExit.depositExitAmount{ value: transferedBalance }(from, transferedBalance, _lockedUserBalanceToNCPTotal[from]); + if (ncpStaking != address(0)) { + _lockedUserBalanceToNCPTotal[from] = 0; + _lockedUserBalanceToNCP[from][ncpStaking] = 0; + } + emit TransferLocked(from, slashing + transferedBalance, _balance[from], availableBalanceOf(from)); + } + + /** + * @dev Unlock fund + * @param payee The address whose funds will be unlocked. + * @param unlockAmount The amount of funds will be unlocked. + */ + function unlock(address payee, uint256 unlockAmount) public override onlyGov { + _unlock(payee, unlockAmount); + } + + function _unlock(address payee, uint256 unlockAmount) internal { + if (unlockAmount == 0) return; + require(_lockedBalance[payee] >= unlockAmount, "Unlock amount should be equal or less than balance locked"); + _lockedBalance[payee] = _lockedBalance[payee] - unlockAmount; + _totalLockedBalance = _totalLockedBalance - unlockAmount; + + emit Unlocked(payee, unlockAmount, _balance[payee], availableBalanceOf(payee)); + } + + function balanceOf(address payee) public view override returns (uint256) { + return _balance[payee]; + } + + function lockedBalanceOf(address payee) public view override returns (uint256) { + return _lockedBalance[payee]; + } + + function availableBalanceOf(address payee) public view override returns (uint256) { + return _balance[payee] - _lockedBalance[payee]; + } + + /** + * @dev Calculate voting weight which range between 0 and 100. + * @param payee The address whose funds were locked. + */ + function calcVotingWeight(address payee) public view override returns (uint256) { + return calcVotingWeightWithScaleFactor(payee, 1e2); + } + + /** + * @dev Calculate voting weight with a scale factor. + * @param payee The address whose funds were locked. + * @param factor The scale factor for weight. For instance: + * if 1e1, result range is between 0 ~ 10 + * if 1e2, result range is between 0 ~ 100 + * if 1e3, result range is between 0 ~ 1000 + */ + function calcVotingWeightWithScaleFactor(address payee, uint32 factor) public view override returns (uint256) { + if (_lockedBalance[payee] == 0 || factor == 0) return 0; + return (_lockedBalance[payee] * factor) / _totalLockedBalance; + } + + function isRevoked() public view returns (bool) { + return revoked; + } + + modifier notRevoked() { + require(!revoked, "Is revoked"); + _; + } + + /** + * @dev Allows the owner to revoke the staking. Funds already staked are returned to the owner + */ + function revoke() public onlyOwner notRevoked { + address contractOwner = owner(); + uint256 balance = address(this).balance; + + require(balance > 0, "balance = 0"); + + payable(contractOwner).transfer(balance); + revoked = true; + + emit Revoked(contractOwner, balance); + } + + function upgradeStaking(address newImp) external onlyOwner { + if (newImp != address(0)) { + _authorizeUpgrade(newImp); + _upgradeToAndCallUUPS(newImp, new bytes(0), false); + } + } + + function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[49] private __gap; + + //Phase2 - Staking + mapping(address /* NCP */ => mapping(address /* user */ => uint256 /* amount */)) private _lockedUserBalanceToNCP; + mapping(address /* NCP */ => uint256 /* amount */) private _lockedUserBalanceToNCPTotal; + + address public ncpStaking; + + modifier onlyNCPStaking() { + require(msg.sender == ncpStaking, "Only NCPStaking contract can call this function"); + _; + } + + function userBalanceOf(address ncp, address user) external view override returns (uint256) { + return _lockedUserBalanceToNCP[ncp][user]; + } + + function userTotalBalanceOf(address ncp) external view override returns (uint256) { + return _lockedUserBalanceToNCPTotal[ncp]; + } + + function getRatioOfUserBalance(address ncp) external view override returns (uint256) { + uint256 user = _lockedUserBalanceToNCPTotal[ncp]; + uint256 locked = _lockedBalance[ncp]; + if (user == 0 || locked == 0) return 0; + return (user * 1e2) / locked; + } + + function setNCPStaking(address _ncpStaking) external onlyOwner { + require(_ncpStaking != address(0), "NCPStaking is the zero address"); + ncpStaking = _ncpStaking; + emit NCPAddrChanged(_ncpStaking); + } + + /** + * @dev Deposit from a user for delegate staking. + */ + function delegateDepositAndLockMore(address ncp) external payable override nonReentrant notRevoked onlyNCPStaking { + require(msg.value > 0, "Deposit amount should be greater than zero"); + require(IGov(getGovAddress()).isMember(ncp), "NCP should be a member"); + + // console.log("delegateDepositAndLockMore: msg.value: %s",ncp); + + uint256 userDepositValue = msg.value; + //added value to ncp balance + _balance[ncp] = _balance[ncp] + userDepositValue; + + uint256 minimum_staking = IEnvStorage(getEnvStorageAddress()).getStakingMin(); + uint256 maximum_staking = IEnvStorage(getEnvStorageAddress()).getStakingMax(); + require( + minimum_staking <= _lockedBalance[ncp] && (_lockedBalance[ncp] + userDepositValue) <= maximum_staking, + "user should be in staking range" + ); + _lock(ncp, userDepositValue); + + _lockedUserBalanceToNCP[ncp][msg.sender] = _lockedUserBalanceToNCP[ncp][msg.sender] + userDepositValue; + _lockedUserBalanceToNCPTotal[ncp] = _lockedUserBalanceToNCPTotal[ncp] + userDepositValue; + + emit DelegateStaked(msg.sender, userDepositValue, ncp, _lockedUserBalanceToNCPTotal[ncp], _lockedUserBalanceToNCP[ncp][msg.sender]); + } + + /** + * @dev Withdraw for a user. + * @param amount The amount of funds will be unlocked, withdrawn and transferred to. + */ + function delegateUnlockAndWithdraw(address ncp, uint256 amount) external override nonReentrant notRevoked onlyNCPStaking { + require(amount > 0, "Amount should be bigger than zero"); + require(IGov(getGovAddress()).isMember(ncp), "NCP should be a member"); + + uint256 userWithdrawValue = amount; + uint256 minimum_staking = IEnvStorage(getEnvStorageAddress()).getStakingMin(); + require( + userWithdrawValue <= _lockedUserBalanceToNCP[ncp][msg.sender] && lockedBalanceOf(ncp) - userWithdrawValue >= minimum_staking, + "Withdraw amount should be equal or less than balance" + ); + _unlock(ncp, userWithdrawValue); + + _balance[ncp] = _balance[ncp] - userWithdrawValue; + _lockedUserBalanceToNCP[ncp][msg.sender] = _lockedUserBalanceToNCP[ncp][msg.sender] - userWithdrawValue; + _lockedUserBalanceToNCPTotal[ncp] = _lockedUserBalanceToNCPTotal[ncp] - userWithdrawValue; + + // payable(ncpStaking).transfer(userWithdrawValue); + (bool succ, ) = payable(ncpStaking).call{ value: userWithdrawValue }(""); + require(succ, "Transfer to NCP staking failed"); + + emit DelegateUnstaked(msg.sender, userWithdrawValue, ncp, _lockedUserBalanceToNCPTotal[ncp], _lockedUserBalanceToNCP[ncp][msg.sender]); + } + + function getTotalLockedBalance() external view override returns (uint256) { + return _totalLockedBalance; + } } diff --git a/wemix/governance-contract/contracts/TestnetGovImp.sol b/wemix/governance-contract/contracts/TestnetGovImp.sol index 2d93d42d8816..a6d0d450863f 100644 --- a/wemix/governance-contract/contracts/TestnetGovImp.sol +++ b/wemix/governance-contract/contracts/TestnetGovImp.sol @@ -13,1019 +13,1019 @@ import "./interface/IStaking.sol"; import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; contract TestnetGovImp is TestnetAGov, ReentrancyGuardUpgradeable, BallotEnums, EnvConstants, UUPSUpgradeable { - enum VariableTypes { - Invalid, - Int, - Uint, - Uint2, - Uint3, - Uint4, - Address, - Bytes32, - Bytes, - String - } - - address constant ZERO = address(0); - - event MemberAdded(address indexed addr, address indexed voter); - event MemberRemoved(address indexed addr, address indexed voter); - event MemberChanged(address indexed oldAddr, address indexed newAddr, address indexed newVoter); - event EnvChanged(bytes32 envName, uint256 envType, bytes envVal); - event MemberUpdated(address indexed addr, address indexed voter); - // added for case that ballot's result could not be applicable. - event NotApplicable(uint256 indexed ballotId, string reason); - - event SetProposalTimePeriod(uint256 newPeriod); - - struct MemberInfo { - address staker; - address voter; // voter - address reward; - bytes name; - bytes enode; - bytes ip; - uint256 port; - uint256 lockAmount; - bytes memo; - uint256 duration; - } - - modifier checkLockedAmount() { - address staker = getStakerAddr(_msgSender()); - require(lockedBalanceOf(staker) <= getMaxStaking() && lockedBalanceOf(staker) >= getMinStaking(), "Invalid staking balance"); - _; - } - - modifier checkTimePeriod() { - address staker = getStakerAddr(_msgSender()); - require((block.timestamp - lastAddProposalTime[staker]) >= proposal_time_period, "Cannot add proposal too early"); - _; - lastAddProposalTime[staker] = block.timestamp; - } - - modifier checkMemberInfo(MemberInfo memory info) { - require(info.voter != ZERO, "Invalid voter"); - require(info.name.length > 0, "Invalid node name"); - require(info.ip.length > 0, "Invalid node IP"); - require(info.port > 0, "Invalid node port"); - require(info.lockAmount >= getMinStaking() && info.lockAmount <= getMaxStaking(), "Invalid lock Amount"); - _; - } - - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - _disableInitializers(); - } - - function init(address registry, uint256 lockAmount, bytes memory name, bytes memory enode, bytes memory ip, uint port) public initializer { - require(lockAmount > 0, "lockAmount should be more then zero"); - __ReentrancyGuard_init(); - __Ownable_init(); - setRegistry(registry); - - // Lock - IStaking staking = IStaking(getStakingAddress()); - require(staking.availableBalanceOf(msg.sender) >= lockAmount, "Insufficient staking"); - staking.lock(msg.sender, lockAmount); - - // Add voting member - memberLength = 1; - voters[memberLength] = msg.sender; - voterIdx[msg.sender] = memberLength; - - // Add reward member - rewards[memberLength] = msg.sender; - rewardIdx[msg.sender] = memberLength; - - stakers[memberLength] = msg.sender; - stakerIdx[msg.sender] = memberLength; - - // Add node - nodeLength = 1; - Node storage node = nodes[nodeLength]; - node.name = name; - node.enode = enode; - node.ip = ip; - node.port = port; - checkNodeName[name] = true; - checkNodeEnode[enode] = true; - - checkNodeIpPort[keccak256(abi.encodePacked(ip, port))] = true; - - nodeIdxFromMember[msg.sender] = nodeLength; - nodeToMember[nodeLength] = msg.sender; - - modifiedBlock = block.number; - } - - function initOnce(address registry, uint256 lockAmount, bytes memory data) public initializer { - __ReentrancyGuard_init(); - __Ownable_init(); - setRegistry(registry); - - // _initialized = true; - modifiedBlock = block.number; - - // Lock - IStaking staking = IStaking(getStakingAddress()); - - require(lockAmount >= getMinStaking() && getMaxStaking() >= lockAmount, "Invalid lock amount"); - - // []{uint staker, uint voter, uint reward, bytes name, bytes enode, bytes ip, uint port} - // 32 bytes, 32 bytes, 32 bytes, [32 bytes, ] * 3, 32 bytes - address staker; - address voter; - address reward; - bytes memory name; - bytes memory enode; - bytes memory ip; - uint port; - uint idx = 0; - - uint ix; - uint eix; - assembly { - ix := add(data, 0x20) - } - eix = ix + data.length; - while (ix < eix) { - assembly { - staker := mload(ix) - } - ix += 0x20; - require(ix < eix); - - assembly { - voter := mload(ix) - } - ix += 0x20; - require(ix < eix); - - assembly { - reward := mload(ix) - } - ix += 0x20; - require(ix < eix); - - assembly { - name := ix - } - ix += 0x20 + name.length; - require(ix < eix); - - assembly { - enode := ix - } - ix += 0x20 + enode.length; - require(ix < eix); - - assembly { - ip := ix - } - ix += 0x20 + ip.length; - require(ix < eix); - - assembly { - port := mload(ix) - } - ix += 0x20; - - idx += 1; - require(!isMember(staker) && !isMember(voter) && !isReward(reward), "Already member"); - voters[idx] = voter; - voterIdx[voter] = idx; - rewards[idx] = reward; - rewardIdx[reward] = idx; - stakers[idx] = staker; - stakerIdx[staker] = idx; - - require(staking.availableBalanceOf(staker) >= lockAmount, "Insufficient staking"); - - require(checkNodeInfoAdd(name, enode, ip, port), "Duplicated node info"); - - lock(staker, lockAmount); - - Node storage node = nodes[idx]; - node.name = name; - node.enode = enode; - node.ip = ip; - node.port = port; - // checkNodeInfo[getNodeInfoHash(enode, ip, port)] = true; - checkNodeName[name] = true; - checkNodeEnode[enode] = true; - checkNodeIpPort[keccak256(abi.encodePacked(ip, port))] = true; - - nodeToMember[idx] = staker; - nodeIdxFromMember[staker] = idx; - } - memberLength = idx; - nodeLength = idx; - } - - //Add member address = staker address = voter address - function addProposalToAddMember( - MemberInfo memory info - ) external onlyGovMem checkTimePeriod checkLockedAmount checkMemberInfo(info) returns (uint256 ballotIdx) { - require(!isMember(info.staker) && !isReward(info.staker), "Already member"); - require(info.staker == info.voter && info.staker == info.reward, "Staker is not voter"); - require(checkNodeInfoAdd(info.name, info.enode, info.ip, info.port), "Duplicated node info"); - ballotIdx = ballotLength + 1; - createBallotForMember( - ballotIdx, // ballot id - uint256(BallotTypes.MemberAdd), // ballot type - msg.sender, // creator - ZERO, // old staker address - info - ); - updateBallotLock(ballotIdx, info.lockAmount); - updateBallotMemo(ballotIdx, info.memo); - ballotLength = ballotIdx; - } - - function addProposalToRemoveMember( - address staker, - uint256 lockAmount, - bytes memory memo, - uint256 duration - ) external onlyGovMem checkTimePeriod checkLockedAmount returns (uint256 ballotIdx) { - require(staker != ZERO, "Invalid address"); - require(isMember(staker), "Non-member"); - require(getMemberLength() > 1, "Cannot remove a sole member"); - require(lockedBalanceOf(staker) >= lockAmount, "Insufficient balance that can be unlocked."); - ballotIdx = ballotLength + 1; - - MemberInfo memory info = MemberInfo( - ZERO, // new staker address - ZERO, - ZERO, - new bytes(0), // new name - new bytes(0), // new enode - new bytes(0), // new ip - 0, // new port - lockAmount, - memo, - duration - ); - createBallotForMember( - ballotIdx, // ballot id - uint256(BallotTypes.MemberRemoval), // ballot type - msg.sender, - staker, - info - ); - updateBallotLock(ballotIdx, lockAmount); - updateBallotMemo(ballotIdx, memo); - ballotLength = ballotIdx; - } - - // voter A, staker A -> voter B, staker B Ok with voting - // voter A, staker B -> voter C, staker C Ok with voting - // voter A, staker B -> voter A, staker A Ok with voting - // voter A call : voter A, staker A -> voter A, staker B X - // staker A call : voter A, staker A-> voter B, staker A Ok without voting - // only staker A call : voter B, staker A, reward C -> voter B, staker A, reward D Ok without voting only (voter can not change reward) - // staker only change own info - // voter can propose and vote anything - function addProposalToChangeMember( - MemberInfo memory newInfo, - address oldStaker - ) external onlyGovMem checkTimePeriod checkLockedAmount checkMemberInfo(newInfo) returns (uint256 ballotIdx) { - require(oldStaker != ZERO, "Invalid old Address"); - require(isMember(oldStaker), "Non-member"); - - require( - (voters[stakerIdx[oldStaker]] == newInfo.voter || - newInfo.voter == oldStaker || - ((!isMember(newInfo.voter)) && !isReward(newInfo.voter))) && - (rewards[stakerIdx[oldStaker]] == newInfo.reward || - newInfo.reward == oldStaker || - ((!isMember(newInfo.reward)) && !isReward(newInfo.reward))), - "Already a member" - ); - - ballotIdx = ballotLength + 1; - createBallotForMember( - ballotIdx, // ballot id - uint256(BallotTypes.MemberChange), // ballot type - msg.sender, // creator - oldStaker, // old staker address - newInfo - ); - updateBallotLock(ballotIdx, newInfo.lockAmount); - updateBallotMemo(ballotIdx, newInfo.memo); - ballotLength = ballotIdx; - // 요청자 == 변경할 voting 주소 - if (msg.sender == oldStaker && oldStaker == newInfo.staker) { - (, , uint256 duration) = getBallotPeriod(ballotIdx); - startBallot(ballotIdx, block.timestamp, block.timestamp + duration); - finalizeVote(ballotIdx, uint256(BallotTypes.MemberChange), true, true); - } - } - - function addProposalToChangeGov( - address newGovAddr, - bytes memory memo, - uint256 duration - ) external onlyGovMem checkLockedAmount returns (uint256 ballotIdx) { - require(newGovAddr != ZERO, "Implementation cannot be zero"); - require(newGovAddr != _getImplementation(), "Same contract address"); - //check newGov has proxiableUUID - try IERC1822Proxiable(newGovAddr).proxiableUUID() returns (bytes32 slot) { - require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); - } catch { - revert("ERC1967Upgrade: new implementation is not UUPS"); - } - ballotIdx = ballotLength + 1; - IBallotStorage(getBallotStorageAddress()).createBallotForAddress( - ballotLength + 1, // ballot id - uint256(BallotTypes.GovernanceChange), // ballot type - duration, - msg.sender, // creator - newGovAddr // new governance address - ); - updateBallotMemo(ballotIdx, memo); - ballotLength = ballotIdx; - } - - function addProposalToChangeEnv( - bytes32 envName, - uint256 envType, - bytes memory envVal, - bytes memory memo, - uint256 duration - ) external onlyGovMem checkTimePeriod checkLockedAmount returns (uint256 ballotIdx) { - // require(envName != 0, "Invalid name"); - require(uint256(VariableTypes.Int) <= envType && envType <= uint256(VariableTypes.String), "Invalid type"); - require(checkVariableCondition(envName, envVal), "Invalid value"); - - ballotIdx = ballotLength + 1; - IBallotStorage(getBallotStorageAddress()).createBallotForVariable( - ballotIdx, // ballot id - uint256(BallotTypes.EnvValChange), // ballot type - duration, - msg.sender, // creator - envName, // env name - envType, // env type - envVal // env value - ); - updateBallotMemo(ballotIdx, memo); - ballotLength = ballotIdx; - } - - function vote(uint256 ballotIdx, bool approval) external onlyGovMem nonReentrant checkLockedAmount { - // Check if some ballot is in progress - require(checkUnfinalized(), "Expired"); - - // Check if the ballot can be voted - uint256 ballotType = checkVotable(ballotIdx); - // Vote - createVote(ballotIdx, approval); - // Finalize - (, uint256 accept, uint256 reject) = getBallotVotingInfo(ballotIdx); - uint256 threshold = getThreshold(); - if (accept >= threshold || reject >= threshold || (accept + reject) == 10000) { - finalizeVote(ballotIdx, ballotType, accept > reject, false); - } - } - - function getMinStaking() public view returns (uint256) { - return IEnvStorage(getEnvStorageAddress()).getStakingMin(); - } - - function getMaxStaking() public view returns (uint256) { - return IEnvStorage(getEnvStorageAddress()).getStakingMax(); - } - - function getMinVotingDuration() public view returns (uint256) { - return IEnvStorage(getEnvStorageAddress()).getBallotDurationMin(); - } - - function getMaxVotingDuration() public view returns (uint256) { - return IEnvStorage(getEnvStorageAddress()).getBallotDurationMax(); - } - - function getThreshold() public pure returns (uint256) { - return 5001; - } // 50.01% from 5001 of 10000 - - function checkUnfinalized() public view returns (bool) { - if (ballotInVoting != 0) { - (, uint256 state, ) = getBallotState(ballotInVoting); - (, uint256 endTime, ) = getBallotPeriod(ballotInVoting); - if (state == uint256(BallotStates.InProgress)) { - if (endTime < block.timestamp) return false; - // require(endTime > block.timestamp, "Expired"); - // require(ballotIdx == ballotInVoting, "Now in voting with different ballot"); - // if (endTime < block.timestamp) { - - // finalizeBallot(ballotInVoting, uint256(BallotStates.Rejected)); - // ballotInVoting = 0; - // // console.log("vote is finalized %s", ballotInVoting); - // } else if (ballotIdx != ballotInVoting) { - // revert("Now in voting with different ballot"); - // } - } - } - return true; - } - - function finalizeEndedVote() public onlyGovMem { - require(!checkUnfinalized(), "Voting is not ended"); - finalizeBallot(ballotInVoting, uint256(BallotStates.Rejected)); - ballotInVoting = 0; - } - - function checkVotable(uint256 ballotIdx) private returns (uint256) { - (uint256 ballotType, uint256 state, ) = getBallotState(ballotIdx); - if (state == uint256(BallotStates.Ready)) { - require(ballotInVoting == 0, "Now in voting with different ballot"); - (, , uint256 duration) = getBallotPeriod(ballotIdx); - if (duration < getMinVotingDuration()) { - startBallot(ballotIdx, block.timestamp, block.timestamp + getMinVotingDuration()); - } else if (getMaxVotingDuration() < duration) { - startBallot(ballotIdx, block.timestamp, block.timestamp + getMaxVotingDuration()); - } else { - startBallot(ballotIdx, block.timestamp, block.timestamp + duration); - } - ballotInVoting = ballotIdx; - } else if (state == uint256(BallotStates.InProgress)) { - // Nothing to do - require(ballotIdx == ballotInVoting, "Now in voting with different ballot"); - } else { - // canceled - revert("Expired"); - } - return ballotType; - } - - function createVote(uint256 ballotIdx, bool approval) private { - uint256 voteIdx = voteLength + 1; - address staker = getStakerAddr(msg.sender); - uint256 weight = 10000 / getMemberLength(); //IStaking(getStakingAddress()).calcVotingWeightWithScaleFactor(staker, 10000); - uint256 decision = approval ? uint256(DecisionTypes.Accept) : uint256(DecisionTypes.Reject); - IBallotStorage(getBallotStorageAddress()).createVote(voteIdx, ballotIdx, staker, decision, weight); - voteLength = voteIdx; - } - - function finalizeVote(uint256 ballotIdx, uint256 ballotType, bool isAccepted, bool self) private { - uint256 ballotState = uint256(BallotStates.Rejected); - if (isAccepted) { - ballotState = uint256(BallotStates.Accepted); - - if (ballotType == uint256(BallotTypes.MemberAdd)) { - if (!addMember(ballotIdx)) { - ballotState = uint256(BallotStates.Rejected); - } - } else if (ballotType == uint256(BallotTypes.MemberRemoval)) { - removeMember(ballotIdx); - } else if (ballotType == uint256(BallotTypes.MemberChange)) { - if (!changeMember(ballotIdx, self)) { - ballotState = uint256(BallotStates.Rejected); - } - } else if (ballotType == uint256(BallotTypes.GovernanceChange)) { - changeGov(ballotIdx); - } else if (ballotType == uint256(BallotTypes.EnvValChange)) { - applyEnv(ballotIdx); - } - } - finalizeBallot(ballotIdx, ballotState); - if (!self) ballotInVoting = 0; - } - - function fromValidBallot(uint256 ballotIdx, uint256 targetType) private view { - (uint256 ballotType, uint256 state, ) = getBallotState(ballotIdx); - require(ballotType == targetType, "Invalid voting type"); - require(state == uint(BallotStates.InProgress), "Invalid voting state"); - (, uint256 accept, uint256 reject) = getBallotVotingInfo(ballotIdx); - require(accept >= getThreshold() || reject >= getThreshold(), "Not yet finalized"); - } - - function addMember(uint256 ballotIdx) private returns (bool) { - fromValidBallot(ballotIdx, uint256(BallotTypes.MemberAdd)); - - ( - , - address newStaker, - address newVoter, - address newReward, - bytes memory name, - bytes memory enode, - bytes memory ip, - uint port, - uint256 lockAmount - ) = getBallotMember(ballotIdx); - if (isMember(newStaker)) { - // new staker is already a member or a voter/ - emit NotApplicable(ballotIdx, "Already a member"); - return false; - } - if (isReward(newReward)) { - // new staker is already a member or a voter/ - emit NotApplicable(ballotIdx, "Already a rewarder"); - return false; - } - - // Lock - if (lockAmount < getMinStaking() || getMaxStaking() < lockAmount) { - emit NotApplicable(ballotIdx, "Invalid lock amount"); - return false; - } - - if (availableBalanceOf(newStaker) < lockAmount) { - emit NotApplicable(ballotIdx, "Insufficient balance that can be locked"); - return false; - } - - if (newStaker != newVoter && newStaker != newReward) { - emit NotApplicable(ballotIdx, "Invalid member address"); - return false; - } - - lock(newStaker, lockAmount); - - // Add voting and reward member - uint256 nMemIdx = memberLength + 1; - voters[nMemIdx] = newVoter; - voterIdx[newVoter] = nMemIdx; - rewards[nMemIdx] = newReward; - rewardIdx[newReward] = nMemIdx; - stakers[nMemIdx] = newStaker; - stakerIdx[newStaker] = nMemIdx; - - // Add node - uint256 nNodeIdx = nodeLength + 1; - Node storage node = nodes[nNodeIdx]; - - node.name = name; - node.enode = enode; - node.ip = ip; - node.port = port; - // checkNodeInfo[getNodeInfoHash(enode, ip, port)] = true; - checkNodeName[name] = true; - checkNodeEnode[enode] = true; - checkNodeIpPort[keccak256(abi.encodePacked(ip, port))] = true; - - nodeToMember[nNodeIdx] = newStaker; - nodeIdxFromMember[newStaker] = nNodeIdx; - node.name = name; - memberLength = nMemIdx; - nodeLength = nNodeIdx; - modifiedBlock = block.number; - emit MemberAdded(newStaker, newVoter); - return true; - } - - function removeMember(uint256 ballotIdx) private { - fromValidBallot(ballotIdx, uint256(BallotTypes.MemberRemoval)); - - (address oldStaker, , , , , , , , uint256 unlockAmount) = getBallotMember(ballotIdx); - if (!isMember(oldStaker)) { - emit NotApplicable(ballotIdx, "Not already a member"); - return; // Non-member. it is abnormal case, but passed - } - - // Remove voting and reward member - uint256 removeIdx = stakerIdx[oldStaker]; - address endAddr = stakers[memberLength]; - address oldVoter = voters[removeIdx]; - address oldReward = rewards[removeIdx]; - - if (stakerIdx[oldStaker] != memberLength) { - (stakers[removeIdx], stakers[memberLength], stakerIdx[oldStaker], stakerIdx[endAddr]) = ( - stakers[memberLength], - ZERO, - 0, - stakerIdx[oldStaker] - ); - removeIdx = rewardIdx[oldStaker]; - endAddr = rewards[memberLength]; - (rewards[removeIdx], rewards[memberLength], rewardIdx[oldReward], rewardIdx[endAddr]) = ( - rewards[memberLength], - ZERO, - 0, - rewardIdx[oldReward] - ); - removeIdx = voterIdx[oldStaker]; - endAddr = voters[memberLength]; - (voters[removeIdx], voters[memberLength], voterIdx[oldVoter], voterIdx[endAddr]) = (voters[memberLength], ZERO, 0, voterIdx[oldVoter]); - } else { - stakers[memberLength] = ZERO; - stakerIdx[oldStaker] = 0; - rewards[memberLength] = ZERO; - rewardIdx[oldReward] = 0; - voters[memberLength] = ZERO; - voterIdx[oldVoter] = 0; - } - memberLength = memberLength - 1; - // Remove node - - Node storage node = nodes[removeIdx]; - checkNodeEnode[node.enode] = false; - checkNodeName[node.name] = false; - checkNodeIpPort[keccak256(abi.encodePacked(node.ip, node.port))] = false; - if (nodeIdxFromMember[oldStaker] != nodeLength) { - removeIdx = nodeIdxFromMember[oldStaker]; - endAddr = nodeToMember[nodeLength]; - - node.name = nodes[nodeLength].name; - node.enode = nodes[nodeLength].enode; - node.ip = nodes[nodeLength].ip; - node.port = nodes[nodeLength].port; - - nodeToMember[removeIdx] = endAddr; - nodeIdxFromMember[endAddr] = removeIdx; - } - nodeToMember[nodeLength] = ZERO; - nodeIdxFromMember[oldStaker] = 0; - delete nodes[nodeLength]; - nodeLength = nodeLength - 1; - modifiedBlock = block.number; - // Unlock and transfer remained to governance - transferLockedAndUnlock(oldStaker, unlockAmount); - - emit MemberRemoved(oldStaker, oldVoter); - } - - function checkChangeMember( - uint256 ballotIdx, - bool self, - address oldStaker, - address newStaker, - address newVoter, - address newReward, - bytes memory name, - bytes memory enode, - bytes memory ip, - uint256 port, - uint256 lockAmount - ) private returns (bool) { - if (!self) { - fromValidBallot(ballotIdx, uint256(BallotTypes.MemberChange)); - } - - if (!isMember(oldStaker)) { - emit NotApplicable(ballotIdx, "Old address is not a member"); - return false; // Non-member. it is abnormal case. - } - - //old staker - uint256 memberIdx = stakerIdx[oldStaker]; - if (oldStaker != newStaker) { - if (isMember(newStaker)) { - emit NotApplicable(ballotIdx, "new address is already a member"); - return false; // already member. it is abnormal case. - } - if (newStaker != newVoter && newStaker != newReward) { - emit NotApplicable(ballotIdx, "Invalid voter address"); - return false; - } - // Lock - if (lockAmount < getMinStaking() || getMaxStaking() < lockAmount) { - emit NotApplicable(ballotIdx, "Invalid lock amount"); - return false; - } - if (availableBalanceOf(newStaker) < lockAmount) { - emit NotApplicable(ballotIdx, "Insufficient balance that can be locked"); - return false; - } - } - // Change node - uint256 nodeIdx = nodeIdxFromMember[oldStaker]; - { - Node memory node = nodes[nodeIdx]; - - if ( - //if node info is not same - // node info can not duplicate - !checkNodeInfoChange(name, enode, ip, port, node) - ) { - emit NotApplicable(ballotIdx, "Duplicated node info"); - return false; - } - } - - { - address oldReward = rewards[memberIdx]; - if ((oldStaker != newReward) && (oldReward != newReward) && (isMember(newReward) || isReward(newReward))) { - emit NotApplicable(ballotIdx, "Invalid reward address"); - return false; - } - } - { - address oldVoter = voters[memberIdx]; - if ((oldStaker != newVoter) && (oldVoter != newVoter) && (isMember(newVoter) || isReward(newVoter))) { - emit NotApplicable(ballotIdx, "Invalid voters address"); - return false; - } - } - return true; - } - - // isMember=> isStaker and isVoter - // vote => onlyVoter, staker can change voter without voting, default = staker == voter - // voter can change staker with voting.(changeMember) - function changeMember(uint256 ballotIdx, bool self) private returns (bool) { - if (!self) { - fromValidBallot(ballotIdx, uint256(BallotTypes.MemberChange)); - } - - ( - address oldStaker, - address newStaker, - address newVoter, - address newReward, - bytes memory name, - bytes memory enode, - bytes memory ip, - uint port, - uint256 lockAmount - ) = getBallotMember(ballotIdx); - if (!isMember(oldStaker)) { - emit NotApplicable(ballotIdx, "Old address is not a member"); - return false; // Non-member. it is abnormal case. - } - - if (!checkChangeMember(ballotIdx, self, oldStaker, newStaker, newVoter, newReward, name, enode, ip, port, lockAmount)) return false; - - //old staker - uint256 memberIdx = stakerIdx[oldStaker]; - if (oldStaker != newStaker) { - // Change member - stakers[memberIdx] = newStaker; - stakerIdx[newStaker] = memberIdx; - stakerIdx[oldStaker] = 0; - - lock(newStaker, lockAmount); - } - // Change node - uint256 nodeIdx = nodeIdxFromMember[oldStaker]; - { - Node storage node = nodes[nodeIdx]; - - checkNodeName[node.name] = false; - checkNodeEnode[node.enode] = false; - checkNodeIpPort[keccak256(abi.encodePacked(node.ip, node.port))] = false; - - node.name = name; - node.enode = enode; - node.ip = ip; - node.port = port; - modifiedBlock = block.number; - // checkNodeInfo[getNodeInfoHash(enode, ip, port)] = true; - checkNodeName[name] = true; - checkNodeEnode[enode] = true; - checkNodeIpPort[keccak256(abi.encodePacked(ip, port))] = true; - } - - { - address oldReward = rewards[memberIdx]; - if (oldReward != newReward) { - rewards[memberIdx] = newReward; - rewardIdx[newReward] = memberIdx; - rewardIdx[oldReward] = 0; - } - } - { - address oldVoter = voters[memberIdx]; - if (oldVoter != newVoter) { - voters[memberIdx] = newVoter; - voterIdx[newVoter] = memberIdx; - voterIdx[oldVoter] = 0; - } - } - - if (oldStaker != newStaker) { - nodeToMember[nodeIdx] = newStaker; - nodeIdxFromMember[newStaker] = nodeIdx; - nodeIdxFromMember[oldStaker] = 0; - - // Unlock and transfer remained to governance - transferLockedAndUnlock(oldStaker, lockAmount); - - emit MemberChanged(oldStaker, newStaker, newVoter); - } else { - emit MemberUpdated(oldStaker, newStaker); - } - return true; - } - - function changeGov(uint256 ballotIdx) private { - fromValidBallot(ballotIdx, uint256(BallotTypes.GovernanceChange)); - - address newImp = IBallotStorage(getBallotStorageAddress()).getBallotAddress(ballotIdx); - if (newImp != ZERO) { - _authorizeUpgrade(newImp); - _upgradeToAndCallUUPS(newImp, new bytes(0), false); - modifiedBlock = block.number; - } - } - - function applyEnv(uint256 ballotIdx) private { - fromValidBallot(ballotIdx, uint256(BallotTypes.EnvValChange)); - - (bytes32 envKey, uint256 envType, bytes memory envVal) = IBallotStorage(getBallotStorageAddress()).getBallotVariable(ballotIdx); - - IEnvStorage envStorage = IEnvStorage(getEnvStorageAddress()); - envStorage.setVariable(envKey, envVal); - modifiedBlock = block.number; - - emit EnvChanged(envKey, envType, envVal); - } - - //------------------ Code reduction for creation gas - function createBallotForMember(uint256 id, uint256 bType, address creator, address oAddr, MemberInfo memory info) private { - IBallotStorage(getBallotStorageAddress()).createBallotForMember( - id, // ballot id - bType, // ballot type - info.duration, - creator, // creator - oAddr, // old member address - info.staker, // new member address - info.voter, // old staker address - info.reward, // new staker address - info.name, // new name - info.enode, // new enode - info.ip, // new ip - info.port // new port - ); - } - - function updateBallotLock(uint256 id, uint256 amount) private { - IBallotStorage(getBallotStorageAddress()).updateBallotMemberLockAmount(id, amount); - } - - function updateBallotMemo(uint256 id, bytes memory memo) private { - IBallotStorage(getBallotStorageAddress()).updateBallotMemo(id, memo); - } - - function startBallot(uint256 id, uint256 s, uint256 e) private { - IBallotStorage(getBallotStorageAddress()).startBallot(id, s, e); - } - - function finalizeBallot(uint256 id, uint256 state) private { - IBallotStorage(getBallotStorageAddress()).finalizeBallot(id, state); - } - - function getBallotState(uint256 id) private view returns (uint256, uint256, bool) { - return IBallotStorage(getBallotStorageAddress()).getBallotState(id); - } - - function getBallotPeriod(uint256 id) private view returns (uint256, uint256, uint256) { - return IBallotStorage(getBallotStorageAddress()).getBallotPeriod(id); - } - - function getBallotVotingInfo(uint256 id) private view returns (uint256, uint256, uint256) { - return IBallotStorage(getBallotStorageAddress()).getBallotVotingInfo(id); - } - - function getBallotMember( - uint256 id - ) private view returns (address, address, address, address, bytes memory, bytes memory, bytes memory, uint256, uint256) { - return IBallotStorage(getBallotStorageAddress()).getBallotMember(id); - } - - function lock(address addr, uint256 amount) private { - IStaking(getStakingAddress()).lock(addr, amount); - } - - function unlock(address addr, uint256 amount) private { - IStaking(getStakingAddress()).unlock(addr, amount); - } - - function transferLockedAndUnlock(address addr, uint256 unlockAmount) private { - IStaking staking = IStaking(getStakingAddress()); - uint256 locked = staking.lockedBalanceOf(addr); - if (locked > unlockAmount) { - staking.transferLocked(addr, locked - unlockAmount); - unlock(addr, unlockAmount); - } else { - unlock(addr, locked); - } - } - - function lockedBalanceOf(address addr) private view returns (uint256) { - // IStaking staking = IStaking(getStakingAddress()).lockedBalanceOf(addr); - return IStaking(getStakingAddress()).lockedBalanceOf(addr); - } - - function availableBalanceOf(address addr) private view returns (uint256) { - return IStaking(getStakingAddress()).availableBalanceOf(addr); - } - - //------------------ Code reduction end - - //====NXTMeta=====/ - - function _authorizeUpgrade(address newImplementation) internal override onlyGovMem {} - - function checkVariableCondition(bytes32 envKey, bytes memory envVal) internal view returns (bool) { - return IEnvStorage(getEnvStorageAddress()).checkVariableCondition(envKey, envVal); - } - - function getStakerAddr(address _addr) public view returns (address staker) { - if (isStaker(_addr)) staker = _addr; - else if (isVoter(_addr)) staker = stakers[voterIdx[_addr]]; - } - - function setProposalTimePeriod(uint256 newPeriod) external onlyOwner { - require(newPeriod < 1 hours, "newPeriod is too long"); - proposal_time_period = newPeriod; - emit SetProposalTimePeriod(newPeriod); - } - - function checkNodeInfoAdd(bytes memory name, bytes memory enode, bytes memory ip, uint port) internal view returns (bool check) { - //Enode can not be duplicated - //IP:port can not be duplicated - //Name can not be duplicated - check = true; - if (checkNodeEnode[enode]) check = false; - if (checkNodeName[name]) check = false; - - bytes32 hvalue = keccak256(abi.encodePacked(ip, port)); - if (checkNodeIpPort[hvalue]) check = false; - } - - function checkNodeInfoChange( - bytes memory name, - bytes memory enode, - bytes memory ip, - uint port, - Node memory nodeInfo - ) internal view returns (bool check) { - //Enode can not be duplicated - //IP:port can not be duplicated - //Name can not be duplicated - check = true; - if ((keccak256(nodeInfo.enode) != keccak256(enode) && checkNodeEnode[enode])) check = false; - if ((keccak256(nodeInfo.name) != keccak256(name) && checkNodeName[name])) check = false; - - bytes32 hvalue = keccak256(abi.encodePacked(ip, port)); - if ((keccak256(abi.encodePacked(nodeInfo.ip, nodeInfo.port)) != hvalue && checkNodeIpPort[hvalue])) check = false; - } - - uint256 public proposal_time_period; - mapping(address => uint256) public lastAddProposalTime; - - //For a node duplicate check - // testnet value is here - // mapping(bytes32=>bool) internal checkNodeInfo; - mapping(bytes => bool) internal checkNodeName; - mapping(bytes => bool) internal checkNodeEnode; - mapping(bytes32 => bool) internal checkNodeIpPort; - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - */ - uint256[46] private __gap; - - function reInit() external reinitializer(2) onlyOwner { - unchecked { - for (uint256 i = 0; i < getMemberLength(); i++) { - Node memory node = nodes[i]; - checkNodeName[node.name] = true; - checkNodeEnode[node.enode] = true; - checkNodeIpPort[keccak256(abi.encodePacked(node.ip, node.port))] = true; - } - } - } - - function reInitV3(uint256[] memory indices, address[] memory newRewards) external reinitializer(3) onlyOwner { - unchecked { - for (uint256 i = 0; i < indices.length; i++) { - address oldReward = rewards[i]; - address newReward = newRewards[i - 1]; - rewards[i] = newReward; - rewardIdx[newReward] = i; - rewardIdx[oldReward] = 0; - } - } - //for the testnet - checkNodeName[nodes[40].name] = true; - checkNodeEnode[nodes[40].enode] = true; - checkNodeIpPort[keccak256(abi.encodePacked(nodes[40].ip, nodes[40].port))] = true; - } - - function maigration(address newGov) external onlyOwner { - IGov(newGov).initMigration(address(reg), modifiedBlock, owner()); - unchecked { - for (uint256 i = 1; i < getMemberLength() + 1; i++) { - IGov(newGov).setMembersForMigration( - i, - stakers[i], - voters[i], - rewards[i], - lastAddProposalTime[stakers[i]], - nodes[i].name, - nodes[i].enode, - nodes[i].ip, - nodes[i].port - ); - } - } - IGov(newGov).setBallotForMigration(ballotLength, voteLength, ballotInVoting); - IGov(newGov).setProposalTimePeriodForMigration(proposal_time_period); - } + enum VariableTypes { + Invalid, + Int, + Uint, + Uint2, + Uint3, + Uint4, + Address, + Bytes32, + Bytes, + String + } + + address constant ZERO = address(0); + + event MemberAdded(address indexed addr, address indexed voter); + event MemberRemoved(address indexed addr, address indexed voter); + event MemberChanged(address indexed oldAddr, address indexed newAddr, address indexed newVoter); + event EnvChanged(bytes32 envName, uint256 envType, bytes envVal); + event MemberUpdated(address indexed addr, address indexed voter); + // added for case that ballot's result could not be applicable. + event NotApplicable(uint256 indexed ballotId, string reason); + + event SetProposalTimePeriod(uint256 newPeriod); + + struct MemberInfo { + address staker; + address voter; // voter + address reward; + bytes name; + bytes enode; + bytes ip; + uint256 port; + uint256 lockAmount; + bytes memo; + uint256 duration; + } + + modifier checkLockedAmount() { + address staker = getStakerAddr(_msgSender()); + require(lockedBalanceOf(staker) <= getMaxStaking() && lockedBalanceOf(staker) >= getMinStaking(), "Invalid staking balance"); + _; + } + + modifier checkTimePeriod() { + address staker = getStakerAddr(_msgSender()); + require((block.timestamp - lastAddProposalTime[staker]) >= proposal_time_period, "Cannot add proposal too early"); + _; + lastAddProposalTime[staker] = block.timestamp; + } + + modifier checkMemberInfo(MemberInfo memory info) { + require(info.voter != ZERO, "Invalid voter"); + require(info.name.length > 0, "Invalid node name"); + require(info.ip.length > 0, "Invalid node IP"); + require(info.port > 0, "Invalid node port"); + require(info.lockAmount >= getMinStaking() && info.lockAmount <= getMaxStaking(), "Invalid lock Amount"); + _; + } + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + function init(address registry, uint256 lockAmount, bytes memory name, bytes memory enode, bytes memory ip, uint port) public initializer { + require(lockAmount > 0, "lockAmount should be more then zero"); + __ReentrancyGuard_init(); + __Ownable_init(); + setRegistry(registry); + + // Lock + IStaking staking = IStaking(getStakingAddress()); + require(staking.availableBalanceOf(msg.sender) >= lockAmount, "Insufficient staking"); + staking.lock(msg.sender, lockAmount); + + // Add voting member + memberLength = 1; + voters[memberLength] = msg.sender; + voterIdx[msg.sender] = memberLength; + + // Add reward member + rewards[memberLength] = msg.sender; + rewardIdx[msg.sender] = memberLength; + + stakers[memberLength] = msg.sender; + stakerIdx[msg.sender] = memberLength; + + // Add node + nodeLength = 1; + Node storage node = nodes[nodeLength]; + node.name = name; + node.enode = enode; + node.ip = ip; + node.port = port; + checkNodeName[name] = true; + checkNodeEnode[enode] = true; + + checkNodeIpPort[keccak256(abi.encodePacked(ip, port))] = true; + + nodeIdxFromMember[msg.sender] = nodeLength; + nodeToMember[nodeLength] = msg.sender; + + modifiedBlock = block.number; + } + + function initOnce(address registry, uint256 lockAmount, bytes memory data) public initializer { + __ReentrancyGuard_init(); + __Ownable_init(); + setRegistry(registry); + + // _initialized = true; + modifiedBlock = block.number; + + // Lock + IStaking staking = IStaking(getStakingAddress()); + + require(lockAmount >= getMinStaking() && getMaxStaking() >= lockAmount, "Invalid lock amount"); + + // []{uint staker, uint voter, uint reward, bytes name, bytes enode, bytes ip, uint port} + // 32 bytes, 32 bytes, 32 bytes, [32 bytes, ] * 3, 32 bytes + address staker; + address voter; + address reward; + bytes memory name; + bytes memory enode; + bytes memory ip; + uint port; + uint idx = 0; + + uint ix; + uint eix; + assembly { + ix := add(data, 0x20) + } + eix = ix + data.length; + while (ix < eix) { + assembly { + staker := mload(ix) + } + ix += 0x20; + require(ix < eix); + + assembly { + voter := mload(ix) + } + ix += 0x20; + require(ix < eix); + + assembly { + reward := mload(ix) + } + ix += 0x20; + require(ix < eix); + + assembly { + name := ix + } + ix += 0x20 + name.length; + require(ix < eix); + + assembly { + enode := ix + } + ix += 0x20 + enode.length; + require(ix < eix); + + assembly { + ip := ix + } + ix += 0x20 + ip.length; + require(ix < eix); + + assembly { + port := mload(ix) + } + ix += 0x20; + + idx += 1; + require(!isMember(staker) && !isMember(voter) && !isReward(reward), "Already member"); + voters[idx] = voter; + voterIdx[voter] = idx; + rewards[idx] = reward; + rewardIdx[reward] = idx; + stakers[idx] = staker; + stakerIdx[staker] = idx; + + require(staking.availableBalanceOf(staker) >= lockAmount, "Insufficient staking"); + + require(checkNodeInfoAdd(name, enode, ip, port), "Duplicated node info"); + + lock(staker, lockAmount); + + Node storage node = nodes[idx]; + node.name = name; + node.enode = enode; + node.ip = ip; + node.port = port; + // checkNodeInfo[getNodeInfoHash(enode, ip, port)] = true; + checkNodeName[name] = true; + checkNodeEnode[enode] = true; + checkNodeIpPort[keccak256(abi.encodePacked(ip, port))] = true; + + nodeToMember[idx] = staker; + nodeIdxFromMember[staker] = idx; + } + memberLength = idx; + nodeLength = idx; + } + + //Add member address = staker address = voter address + function addProposalToAddMember( + MemberInfo memory info + ) external onlyGovMem checkTimePeriod checkLockedAmount checkMemberInfo(info) returns (uint256 ballotIdx) { + require(!isMember(info.staker) && !isReward(info.staker), "Already member"); + require(info.staker == info.voter && info.staker == info.reward, "Staker is not voter"); + require(checkNodeInfoAdd(info.name, info.enode, info.ip, info.port), "Duplicated node info"); + ballotIdx = ballotLength + 1; + createBallotForMember( + ballotIdx, // ballot id + uint256(BallotTypes.MemberAdd), // ballot type + msg.sender, // creator + ZERO, // old staker address + info + ); + updateBallotLock(ballotIdx, info.lockAmount); + updateBallotMemo(ballotIdx, info.memo); + ballotLength = ballotIdx; + } + + function addProposalToRemoveMember( + address staker, + uint256 lockAmount, + bytes memory memo, + uint256 duration + ) external onlyGovMem checkTimePeriod checkLockedAmount returns (uint256 ballotIdx) { + require(staker != ZERO, "Invalid address"); + require(isMember(staker), "Non-member"); + require(getMemberLength() > 1, "Cannot remove a sole member"); + require(lockedBalanceOf(staker) >= lockAmount, "Insufficient balance that can be unlocked."); + ballotIdx = ballotLength + 1; + + MemberInfo memory info = MemberInfo( + ZERO, // new staker address + ZERO, + ZERO, + new bytes(0), // new name + new bytes(0), // new enode + new bytes(0), // new ip + 0, // new port + lockAmount, + memo, + duration + ); + createBallotForMember( + ballotIdx, // ballot id + uint256(BallotTypes.MemberRemoval), // ballot type + msg.sender, + staker, + info + ); + updateBallotLock(ballotIdx, lockAmount); + updateBallotMemo(ballotIdx, memo); + ballotLength = ballotIdx; + } + + // voter A, staker A -> voter B, staker B Ok with voting + // voter A, staker B -> voter C, staker C Ok with voting + // voter A, staker B -> voter A, staker A Ok with voting + // voter A call : voter A, staker A -> voter A, staker B X + // staker A call : voter A, staker A-> voter B, staker A Ok without voting + // only staker A call : voter B, staker A, reward C -> voter B, staker A, reward D Ok without voting only (voter can not change reward) + // staker only change own info + // voter can propose and vote anything + function addProposalToChangeMember( + MemberInfo memory newInfo, + address oldStaker + ) external onlyGovMem checkTimePeriod checkLockedAmount checkMemberInfo(newInfo) returns (uint256 ballotIdx) { + require(oldStaker != ZERO, "Invalid old Address"); + require(isMember(oldStaker), "Non-member"); + + require( + (voters[stakerIdx[oldStaker]] == newInfo.voter || + newInfo.voter == oldStaker || + ((!isMember(newInfo.voter)) && !isReward(newInfo.voter))) && + (rewards[stakerIdx[oldStaker]] == newInfo.reward || + newInfo.reward == oldStaker || + ((!isMember(newInfo.reward)) && !isReward(newInfo.reward))), + "Already a member" + ); + + ballotIdx = ballotLength + 1; + createBallotForMember( + ballotIdx, // ballot id + uint256(BallotTypes.MemberChange), // ballot type + msg.sender, // creator + oldStaker, // old staker address + newInfo + ); + updateBallotLock(ballotIdx, newInfo.lockAmount); + updateBallotMemo(ballotIdx, newInfo.memo); + ballotLength = ballotIdx; + // 요청자 == 변경할 voting 주소 + if (msg.sender == oldStaker && oldStaker == newInfo.staker) { + (, , uint256 duration) = getBallotPeriod(ballotIdx); + startBallot(ballotIdx, block.timestamp, block.timestamp + duration); + finalizeVote(ballotIdx, uint256(BallotTypes.MemberChange), true, true); + } + } + + function addProposalToChangeGov( + address newGovAddr, + bytes memory memo, + uint256 duration + ) external onlyGovMem checkLockedAmount returns (uint256 ballotIdx) { + require(newGovAddr != ZERO, "Implementation cannot be zero"); + require(newGovAddr != _getImplementation(), "Same contract address"); + //check newGov has proxiableUUID + try IERC1822Proxiable(newGovAddr).proxiableUUID() returns (bytes32 slot) { + require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); + } catch { + revert("ERC1967Upgrade: new implementation is not UUPS"); + } + ballotIdx = ballotLength + 1; + IBallotStorage(getBallotStorageAddress()).createBallotForAddress( + ballotLength + 1, // ballot id + uint256(BallotTypes.GovernanceChange), // ballot type + duration, + msg.sender, // creator + newGovAddr // new governance address + ); + updateBallotMemo(ballotIdx, memo); + ballotLength = ballotIdx; + } + + function addProposalToChangeEnv( + bytes32 envName, + uint256 envType, + bytes memory envVal, + bytes memory memo, + uint256 duration + ) external onlyGovMem checkTimePeriod checkLockedAmount returns (uint256 ballotIdx) { + // require(envName != 0, "Invalid name"); + require(uint256(VariableTypes.Int) <= envType && envType <= uint256(VariableTypes.String), "Invalid type"); + require(checkVariableCondition(envName, envVal), "Invalid value"); + + ballotIdx = ballotLength + 1; + IBallotStorage(getBallotStorageAddress()).createBallotForVariable( + ballotIdx, // ballot id + uint256(BallotTypes.EnvValChange), // ballot type + duration, + msg.sender, // creator + envName, // env name + envType, // env type + envVal // env value + ); + updateBallotMemo(ballotIdx, memo); + ballotLength = ballotIdx; + } + + function vote(uint256 ballotIdx, bool approval) external onlyGovMem nonReentrant checkLockedAmount { + // Check if some ballot is in progress + require(checkUnfinalized(), "Expired"); + + // Check if the ballot can be voted + uint256 ballotType = checkVotable(ballotIdx); + // Vote + createVote(ballotIdx, approval); + // Finalize + (, uint256 accept, uint256 reject) = getBallotVotingInfo(ballotIdx); + uint256 threshold = getThreshold(); + if (accept >= threshold || reject >= threshold || (accept + reject) == 10000) { + finalizeVote(ballotIdx, ballotType, accept > reject, false); + } + } + + function getMinStaking() public view returns (uint256) { + return IEnvStorage(getEnvStorageAddress()).getStakingMin(); + } + + function getMaxStaking() public view returns (uint256) { + return IEnvStorage(getEnvStorageAddress()).getStakingMax(); + } + + function getMinVotingDuration() public view returns (uint256) { + return IEnvStorage(getEnvStorageAddress()).getBallotDurationMin(); + } + + function getMaxVotingDuration() public view returns (uint256) { + return IEnvStorage(getEnvStorageAddress()).getBallotDurationMax(); + } + + function getThreshold() public pure returns (uint256) { + return 5001; + } // 50.01% from 5001 of 10000 + + function checkUnfinalized() public view returns (bool) { + if (ballotInVoting != 0) { + (, uint256 state, ) = getBallotState(ballotInVoting); + (, uint256 endTime, ) = getBallotPeriod(ballotInVoting); + if (state == uint256(BallotStates.InProgress)) { + if (endTime < block.timestamp) return false; + // require(endTime > block.timestamp, "Expired"); + // require(ballotIdx == ballotInVoting, "Now in voting with different ballot"); + // if (endTime < block.timestamp) { + + // finalizeBallot(ballotInVoting, uint256(BallotStates.Rejected)); + // ballotInVoting = 0; + // // console.log("vote is finalized %s", ballotInVoting); + // } else if (ballotIdx != ballotInVoting) { + // revert("Now in voting with different ballot"); + // } + } + } + return true; + } + + function finalizeEndedVote() public onlyGovMem { + require(!checkUnfinalized(), "Voting is not ended"); + finalizeBallot(ballotInVoting, uint256(BallotStates.Rejected)); + ballotInVoting = 0; + } + + function checkVotable(uint256 ballotIdx) private returns (uint256) { + (uint256 ballotType, uint256 state, ) = getBallotState(ballotIdx); + if (state == uint256(BallotStates.Ready)) { + require(ballotInVoting == 0, "Now in voting with different ballot"); + (, , uint256 duration) = getBallotPeriod(ballotIdx); + if (duration < getMinVotingDuration()) { + startBallot(ballotIdx, block.timestamp, block.timestamp + getMinVotingDuration()); + } else if (getMaxVotingDuration() < duration) { + startBallot(ballotIdx, block.timestamp, block.timestamp + getMaxVotingDuration()); + } else { + startBallot(ballotIdx, block.timestamp, block.timestamp + duration); + } + ballotInVoting = ballotIdx; + } else if (state == uint256(BallotStates.InProgress)) { + // Nothing to do + require(ballotIdx == ballotInVoting, "Now in voting with different ballot"); + } else { + // canceled + revert("Expired"); + } + return ballotType; + } + + function createVote(uint256 ballotIdx, bool approval) private { + uint256 voteIdx = voteLength + 1; + address staker = getStakerAddr(msg.sender); + uint256 weight = 10000 / getMemberLength(); //IStaking(getStakingAddress()).calcVotingWeightWithScaleFactor(staker, 10000); + uint256 decision = approval ? uint256(DecisionTypes.Accept) : uint256(DecisionTypes.Reject); + IBallotStorage(getBallotStorageAddress()).createVote(voteIdx, ballotIdx, staker, decision, weight); + voteLength = voteIdx; + } + + function finalizeVote(uint256 ballotIdx, uint256 ballotType, bool isAccepted, bool self) private { + uint256 ballotState = uint256(BallotStates.Rejected); + if (isAccepted) { + ballotState = uint256(BallotStates.Accepted); + + if (ballotType == uint256(BallotTypes.MemberAdd)) { + if (!addMember(ballotIdx)) { + ballotState = uint256(BallotStates.Rejected); + } + } else if (ballotType == uint256(BallotTypes.MemberRemoval)) { + removeMember(ballotIdx); + } else if (ballotType == uint256(BallotTypes.MemberChange)) { + if (!changeMember(ballotIdx, self)) { + ballotState = uint256(BallotStates.Rejected); + } + } else if (ballotType == uint256(BallotTypes.GovernanceChange)) { + changeGov(ballotIdx); + } else if (ballotType == uint256(BallotTypes.EnvValChange)) { + applyEnv(ballotIdx); + } + } + finalizeBallot(ballotIdx, ballotState); + if (!self) ballotInVoting = 0; + } + + function fromValidBallot(uint256 ballotIdx, uint256 targetType) private view { + (uint256 ballotType, uint256 state, ) = getBallotState(ballotIdx); + require(ballotType == targetType, "Invalid voting type"); + require(state == uint(BallotStates.InProgress), "Invalid voting state"); + (, uint256 accept, uint256 reject) = getBallotVotingInfo(ballotIdx); + require(accept >= getThreshold() || reject >= getThreshold(), "Not yet finalized"); + } + + function addMember(uint256 ballotIdx) private returns (bool) { + fromValidBallot(ballotIdx, uint256(BallotTypes.MemberAdd)); + + ( + , + address newStaker, + address newVoter, + address newReward, + bytes memory name, + bytes memory enode, + bytes memory ip, + uint port, + uint256 lockAmount + ) = getBallotMember(ballotIdx); + if (isMember(newStaker)) { + // new staker is already a member or a voter/ + emit NotApplicable(ballotIdx, "Already a member"); + return false; + } + if (isReward(newReward)) { + // new staker is already a member or a voter/ + emit NotApplicable(ballotIdx, "Already a rewarder"); + return false; + } + + // Lock + if (lockAmount < getMinStaking() || getMaxStaking() < lockAmount) { + emit NotApplicable(ballotIdx, "Invalid lock amount"); + return false; + } + + if (availableBalanceOf(newStaker) < lockAmount) { + emit NotApplicable(ballotIdx, "Insufficient balance that can be locked"); + return false; + } + + if (newStaker != newVoter && newStaker != newReward) { + emit NotApplicable(ballotIdx, "Invalid member address"); + return false; + } + + lock(newStaker, lockAmount); + + // Add voting and reward member + uint256 nMemIdx = memberLength + 1; + voters[nMemIdx] = newVoter; + voterIdx[newVoter] = nMemIdx; + rewards[nMemIdx] = newReward; + rewardIdx[newReward] = nMemIdx; + stakers[nMemIdx] = newStaker; + stakerIdx[newStaker] = nMemIdx; + + // Add node + uint256 nNodeIdx = nodeLength + 1; + Node storage node = nodes[nNodeIdx]; + + node.name = name; + node.enode = enode; + node.ip = ip; + node.port = port; + // checkNodeInfo[getNodeInfoHash(enode, ip, port)] = true; + checkNodeName[name] = true; + checkNodeEnode[enode] = true; + checkNodeIpPort[keccak256(abi.encodePacked(ip, port))] = true; + + nodeToMember[nNodeIdx] = newStaker; + nodeIdxFromMember[newStaker] = nNodeIdx; + node.name = name; + memberLength = nMemIdx; + nodeLength = nNodeIdx; + modifiedBlock = block.number; + emit MemberAdded(newStaker, newVoter); + return true; + } + + function removeMember(uint256 ballotIdx) private { + fromValidBallot(ballotIdx, uint256(BallotTypes.MemberRemoval)); + + (address oldStaker, , , , , , , , uint256 unlockAmount) = getBallotMember(ballotIdx); + if (!isMember(oldStaker)) { + emit NotApplicable(ballotIdx, "Not already a member"); + return; // Non-member. it is abnormal case, but passed + } + + // Remove voting and reward member + uint256 removeIdx = stakerIdx[oldStaker]; + address endAddr = stakers[memberLength]; + address oldVoter = voters[removeIdx]; + address oldReward = rewards[removeIdx]; + + if (stakerIdx[oldStaker] != memberLength) { + (stakers[removeIdx], stakers[memberLength], stakerIdx[oldStaker], stakerIdx[endAddr]) = ( + stakers[memberLength], + ZERO, + 0, + stakerIdx[oldStaker] + ); + removeIdx = rewardIdx[oldStaker]; + endAddr = rewards[memberLength]; + (rewards[removeIdx], rewards[memberLength], rewardIdx[oldReward], rewardIdx[endAddr]) = ( + rewards[memberLength], + ZERO, + 0, + rewardIdx[oldReward] + ); + removeIdx = voterIdx[oldStaker]; + endAddr = voters[memberLength]; + (voters[removeIdx], voters[memberLength], voterIdx[oldVoter], voterIdx[endAddr]) = (voters[memberLength], ZERO, 0, voterIdx[oldVoter]); + } else { + stakers[memberLength] = ZERO; + stakerIdx[oldStaker] = 0; + rewards[memberLength] = ZERO; + rewardIdx[oldReward] = 0; + voters[memberLength] = ZERO; + voterIdx[oldVoter] = 0; + } + memberLength = memberLength - 1; + // Remove node + + Node storage node = nodes[removeIdx]; + checkNodeEnode[node.enode] = false; + checkNodeName[node.name] = false; + checkNodeIpPort[keccak256(abi.encodePacked(node.ip, node.port))] = false; + if (nodeIdxFromMember[oldStaker] != nodeLength) { + removeIdx = nodeIdxFromMember[oldStaker]; + endAddr = nodeToMember[nodeLength]; + + node.name = nodes[nodeLength].name; + node.enode = nodes[nodeLength].enode; + node.ip = nodes[nodeLength].ip; + node.port = nodes[nodeLength].port; + + nodeToMember[removeIdx] = endAddr; + nodeIdxFromMember[endAddr] = removeIdx; + } + nodeToMember[nodeLength] = ZERO; + nodeIdxFromMember[oldStaker] = 0; + delete nodes[nodeLength]; + nodeLength = nodeLength - 1; + modifiedBlock = block.number; + // Unlock and transfer remained to governance + transferLockedAndUnlock(oldStaker, unlockAmount); + + emit MemberRemoved(oldStaker, oldVoter); + } + + function checkChangeMember( + uint256 ballotIdx, + bool self, + address oldStaker, + address newStaker, + address newVoter, + address newReward, + bytes memory name, + bytes memory enode, + bytes memory ip, + uint256 port, + uint256 lockAmount + ) private returns (bool) { + if (!self) { + fromValidBallot(ballotIdx, uint256(BallotTypes.MemberChange)); + } + + if (!isMember(oldStaker)) { + emit NotApplicable(ballotIdx, "Old address is not a member"); + return false; // Non-member. it is abnormal case. + } + + //old staker + uint256 memberIdx = stakerIdx[oldStaker]; + if (oldStaker != newStaker) { + if (isMember(newStaker)) { + emit NotApplicable(ballotIdx, "new address is already a member"); + return false; // already member. it is abnormal case. + } + if (newStaker != newVoter && newStaker != newReward) { + emit NotApplicable(ballotIdx, "Invalid voter address"); + return false; + } + // Lock + if (lockAmount < getMinStaking() || getMaxStaking() < lockAmount) { + emit NotApplicable(ballotIdx, "Invalid lock amount"); + return false; + } + if (availableBalanceOf(newStaker) < lockAmount) { + emit NotApplicable(ballotIdx, "Insufficient balance that can be locked"); + return false; + } + } + // Change node + uint256 nodeIdx = nodeIdxFromMember[oldStaker]; + { + Node memory node = nodes[nodeIdx]; + + if ( + //if node info is not same + // node info can not duplicate + !checkNodeInfoChange(name, enode, ip, port, node) + ) { + emit NotApplicable(ballotIdx, "Duplicated node info"); + return false; + } + } + + { + address oldReward = rewards[memberIdx]; + if ((oldStaker != newReward) && (oldReward != newReward) && (isMember(newReward) || isReward(newReward))) { + emit NotApplicable(ballotIdx, "Invalid reward address"); + return false; + } + } + { + address oldVoter = voters[memberIdx]; + if ((oldStaker != newVoter) && (oldVoter != newVoter) && (isMember(newVoter) || isReward(newVoter))) { + emit NotApplicable(ballotIdx, "Invalid voters address"); + return false; + } + } + return true; + } + + // isMember=> isStaker and isVoter + // vote => onlyVoter, staker can change voter without voting, default = staker == voter + // voter can change staker with voting.(changeMember) + function changeMember(uint256 ballotIdx, bool self) private returns (bool) { + if (!self) { + fromValidBallot(ballotIdx, uint256(BallotTypes.MemberChange)); + } + + ( + address oldStaker, + address newStaker, + address newVoter, + address newReward, + bytes memory name, + bytes memory enode, + bytes memory ip, + uint port, + uint256 lockAmount + ) = getBallotMember(ballotIdx); + if (!isMember(oldStaker)) { + emit NotApplicable(ballotIdx, "Old address is not a member"); + return false; // Non-member. it is abnormal case. + } + + if (!checkChangeMember(ballotIdx, self, oldStaker, newStaker, newVoter, newReward, name, enode, ip, port, lockAmount)) return false; + + //old staker + uint256 memberIdx = stakerIdx[oldStaker]; + if (oldStaker != newStaker) { + // Change member + stakers[memberIdx] = newStaker; + stakerIdx[newStaker] = memberIdx; + stakerIdx[oldStaker] = 0; + + lock(newStaker, lockAmount); + } + // Change node + uint256 nodeIdx = nodeIdxFromMember[oldStaker]; + { + Node storage node = nodes[nodeIdx]; + + checkNodeName[node.name] = false; + checkNodeEnode[node.enode] = false; + checkNodeIpPort[keccak256(abi.encodePacked(node.ip, node.port))] = false; + + node.name = name; + node.enode = enode; + node.ip = ip; + node.port = port; + modifiedBlock = block.number; + // checkNodeInfo[getNodeInfoHash(enode, ip, port)] = true; + checkNodeName[name] = true; + checkNodeEnode[enode] = true; + checkNodeIpPort[keccak256(abi.encodePacked(ip, port))] = true; + } + + { + address oldReward = rewards[memberIdx]; + if (oldReward != newReward) { + rewards[memberIdx] = newReward; + rewardIdx[newReward] = memberIdx; + rewardIdx[oldReward] = 0; + } + } + { + address oldVoter = voters[memberIdx]; + if (oldVoter != newVoter) { + voters[memberIdx] = newVoter; + voterIdx[newVoter] = memberIdx; + voterIdx[oldVoter] = 0; + } + } + + if (oldStaker != newStaker) { + nodeToMember[nodeIdx] = newStaker; + nodeIdxFromMember[newStaker] = nodeIdx; + nodeIdxFromMember[oldStaker] = 0; + + // Unlock and transfer remained to governance + transferLockedAndUnlock(oldStaker, lockAmount); + + emit MemberChanged(oldStaker, newStaker, newVoter); + } else { + emit MemberUpdated(oldStaker, newStaker); + } + return true; + } + + function changeGov(uint256 ballotIdx) private { + fromValidBallot(ballotIdx, uint256(BallotTypes.GovernanceChange)); + + address newImp = IBallotStorage(getBallotStorageAddress()).getBallotAddress(ballotIdx); + if (newImp != ZERO) { + _authorizeUpgrade(newImp); + _upgradeToAndCallUUPS(newImp, new bytes(0), false); + modifiedBlock = block.number; + } + } + + function applyEnv(uint256 ballotIdx) private { + fromValidBallot(ballotIdx, uint256(BallotTypes.EnvValChange)); + + (bytes32 envKey, uint256 envType, bytes memory envVal) = IBallotStorage(getBallotStorageAddress()).getBallotVariable(ballotIdx); + + IEnvStorage envStorage = IEnvStorage(getEnvStorageAddress()); + envStorage.setVariable(envKey, envVal); + modifiedBlock = block.number; + + emit EnvChanged(envKey, envType, envVal); + } + + //------------------ Code reduction for creation gas + function createBallotForMember(uint256 id, uint256 bType, address creator, address oAddr, MemberInfo memory info) private { + IBallotStorage(getBallotStorageAddress()).createBallotForMember( + id, // ballot id + bType, // ballot type + info.duration, + creator, // creator + oAddr, // old member address + info.staker, // new member address + info.voter, // old staker address + info.reward, // new staker address + info.name, // new name + info.enode, // new enode + info.ip, // new ip + info.port // new port + ); + } + + function updateBallotLock(uint256 id, uint256 amount) private { + IBallotStorage(getBallotStorageAddress()).updateBallotMemberLockAmount(id, amount); + } + + function updateBallotMemo(uint256 id, bytes memory memo) private { + IBallotStorage(getBallotStorageAddress()).updateBallotMemo(id, memo); + } + + function startBallot(uint256 id, uint256 s, uint256 e) private { + IBallotStorage(getBallotStorageAddress()).startBallot(id, s, e); + } + + function finalizeBallot(uint256 id, uint256 state) private { + IBallotStorage(getBallotStorageAddress()).finalizeBallot(id, state); + } + + function getBallotState(uint256 id) private view returns (uint256, uint256, bool) { + return IBallotStorage(getBallotStorageAddress()).getBallotState(id); + } + + function getBallotPeriod(uint256 id) private view returns (uint256, uint256, uint256) { + return IBallotStorage(getBallotStorageAddress()).getBallotPeriod(id); + } + + function getBallotVotingInfo(uint256 id) private view returns (uint256, uint256, uint256) { + return IBallotStorage(getBallotStorageAddress()).getBallotVotingInfo(id); + } + + function getBallotMember( + uint256 id + ) private view returns (address, address, address, address, bytes memory, bytes memory, bytes memory, uint256, uint256) { + return IBallotStorage(getBallotStorageAddress()).getBallotMember(id); + } + + function lock(address addr, uint256 amount) private { + IStaking(getStakingAddress()).lock(addr, amount); + } + + function unlock(address addr, uint256 amount) private { + IStaking(getStakingAddress()).unlock(addr, amount); + } + + function transferLockedAndUnlock(address addr, uint256 unlockAmount) private { + IStaking staking = IStaking(getStakingAddress()); + uint256 locked = staking.lockedBalanceOf(addr); + if (locked > unlockAmount) { + staking.transferLocked(addr, locked - unlockAmount); + unlock(addr, unlockAmount); + } else { + unlock(addr, locked); + } + } + + function lockedBalanceOf(address addr) private view returns (uint256) { + // IStaking staking = IStaking(getStakingAddress()).lockedBalanceOf(addr); + return IStaking(getStakingAddress()).lockedBalanceOf(addr); + } + + function availableBalanceOf(address addr) private view returns (uint256) { + return IStaking(getStakingAddress()).availableBalanceOf(addr); + } + + //------------------ Code reduction end + + //====NXTMeta=====/ + + function _authorizeUpgrade(address newImplementation) internal override onlyGovMem {} + + function checkVariableCondition(bytes32 envKey, bytes memory envVal) internal view returns (bool) { + return IEnvStorage(getEnvStorageAddress()).checkVariableCondition(envKey, envVal); + } + + function getStakerAddr(address _addr) public view returns (address staker) { + if (isStaker(_addr)) staker = _addr; + else if (isVoter(_addr)) staker = stakers[voterIdx[_addr]]; + } + + function setProposalTimePeriod(uint256 newPeriod) external onlyOwner { + require(newPeriod < 1 hours, "newPeriod is too long"); + proposal_time_period = newPeriod; + emit SetProposalTimePeriod(newPeriod); + } + + function checkNodeInfoAdd(bytes memory name, bytes memory enode, bytes memory ip, uint port) internal view returns (bool check) { + //Enode can not be duplicated + //IP:port can not be duplicated + //Name can not be duplicated + check = true; + if (checkNodeEnode[enode]) check = false; + if (checkNodeName[name]) check = false; + + bytes32 hvalue = keccak256(abi.encodePacked(ip, port)); + if (checkNodeIpPort[hvalue]) check = false; + } + + function checkNodeInfoChange( + bytes memory name, + bytes memory enode, + bytes memory ip, + uint port, + Node memory nodeInfo + ) internal view returns (bool check) { + //Enode can not be duplicated + //IP:port can not be duplicated + //Name can not be duplicated + check = true; + if ((keccak256(nodeInfo.enode) != keccak256(enode) && checkNodeEnode[enode])) check = false; + if ((keccak256(nodeInfo.name) != keccak256(name) && checkNodeName[name])) check = false; + + bytes32 hvalue = keccak256(abi.encodePacked(ip, port)); + if ((keccak256(abi.encodePacked(nodeInfo.ip, nodeInfo.port)) != hvalue && checkNodeIpPort[hvalue])) check = false; + } + + uint256 public proposal_time_period; + mapping(address => uint256) public lastAddProposalTime; + + //For a node duplicate check + // testnet value is here + // mapping(bytes32=>bool) internal checkNodeInfo; + mapping(bytes => bool) internal checkNodeName; + mapping(bytes => bool) internal checkNodeEnode; + mapping(bytes32 => bool) internal checkNodeIpPort; + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[46] private __gap; + + function reInit() external reinitializer(2) onlyOwner { + unchecked { + for (uint256 i = 0; i < getMemberLength(); i++) { + Node memory node = nodes[i]; + checkNodeName[node.name] = true; + checkNodeEnode[node.enode] = true; + checkNodeIpPort[keccak256(abi.encodePacked(node.ip, node.port))] = true; + } + } + } + + function reInitV3(uint256[] memory indices, address[] memory newRewards) external reinitializer(3) onlyOwner { + unchecked { + for (uint256 i = 0; i < indices.length; i++) { + address oldReward = rewards[i]; + address newReward = newRewards[i - 1]; + rewards[i] = newReward; + rewardIdx[newReward] = i; + rewardIdx[oldReward] = 0; + } + } + //for the testnet + checkNodeName[nodes[40].name] = true; + checkNodeEnode[nodes[40].enode] = true; + checkNodeIpPort[keccak256(abi.encodePacked(nodes[40].ip, nodes[40].port))] = true; + } + + function maigration(address newGov) external onlyOwner { + IGov(newGov).initMigration(address(reg), modifiedBlock, owner()); + unchecked { + for (uint256 i = 1; i < getMemberLength() + 1; i++) { + IGov(newGov).setMembersForMigration( + i, + stakers[i], + voters[i], + rewards[i], + lastAddProposalTime[stakers[i]], + nodes[i].name, + nodes[i].enode, + nodes[i].ip, + nodes[i].port + ); + } + } + IGov(newGov).setBallotForMigration(ballotLength, voteLength, ballotInVoting); + IGov(newGov).setProposalTimePeriodForMigration(proposal_time_period); + } } diff --git a/wemix/governance-contract/contracts/abstract/AEnvStorage.sol b/wemix/governance-contract/contracts/abstract/AEnvStorage.sol index 2d238c6884e2..7b1fd0286ec4 100644 --- a/wemix/governance-contract/contracts/abstract/AEnvStorage.sol +++ b/wemix/governance-contract/contracts/abstract/AEnvStorage.sol @@ -5,130 +5,130 @@ import "../GovChecker.sol"; import "../storage/EternalStorage.sol"; abstract contract AEnvStorage is EternalStorage, GovChecker { - event StringVarableChanged(bytes32 indexed _name, string _value); - - event UintVarableChanged(bytes32 indexed _name, uint _value); - - event IntVarableChanged(bytes32 indexed _name, int _value); - - event AddressVarableChanged(bytes32 indexed _name, address _value); - - event Bytes32VarableChanged(bytes32 indexed _name, bytes32 _value); - - event BytesVarableChanged(bytes32 indexed _name, bytes _value); - - event VarableChanged(bytes32 indexed _name, uint256 indexed _type, string _value); - - /** - * @dev Allows the owner to set a value for a int variable - * @param h The keccak256 hash of the variable name - * @param v The value to be stored - */ - function setInt(bytes32 h, int256 v) internal { - _setInt(h, v); - emit IntVarableChanged(h, v); - } - - /** - * @dev Allows the owner to set a value for a boolean variable - * @param h The keccak256 hash of the variable name - * @param v The value to be stored - */ - function setUint(bytes32 h, uint256 v) internal { - _setUint(h, v); - emit UintVarableChanged(h, v); - } - - /** - * @dev Allows the owner to set a value for a address variable - * @param h The keccak256 hash of the variable name - * @param v The value to be stored - */ - function setAddress(bytes32 h, address v) internal { - _setAddress(h, v); - emit AddressVarableChanged(h, v); - } - - /** - * @dev Allows the owner to set a value for a string variable - * @param h The keccak256 hash of the variable name - * @param v The value to be stored - */ - function setString(bytes32 h, string memory v) internal { - _setString(h, v); - emit StringVarableChanged(h, v); - } - - /** - * @dev Allows the owner to set a value for a bytes variable - * @param h The keccak256 hash of the variable name - * @param v The value to be stored - */ - function setBytes(bytes32 h, bytes memory v) internal { - _setBytes(h, v); - emit BytesVarableChanged(h, v); - } - - /** - * @dev Allows the owner to set a value for a bytes32 variable - * @param h The keccak256 hash of the variable name - * @param v The value to be stored - */ - function setBytes32(bytes32 h, bytes32 v) internal { - _setBytes32(h, v); - emit Bytes32VarableChanged(h, v); - } - - // mapping(bytes32 => Variable) internal s; - - // /** - // * @dev Add a new variable . - // * @param _h The keccak256 hash of the variable name - // * @param _t The type of value - // * @param _v The value to be stored - // */ - // function _add(bytes32 _h, uint256 _t, string _v) internal { - // require(s[_h]._name == "","not found"); - // s[_h] = Variable(_h,_t,_v); - // emit VarableAdded(_h,_t,_v); - // } - // /** - // * @dev Update a new variable . - // * @param _h The keccak256 hash of the variable name - // * @param _t The type of value - // * @param _v The value to be stored - // */ - // function _change(bytes32 _h, uint256 _t, string _v) internal { - // require(s[_h]._name == _h,"not found"); - // Variable storage v = s[_h]; - // v._name = _h; - // v._type = _t; - // v._value = _v; - // emit VarableChanged(_h,_t,_v); - - // } - // /** - // * @dev Get the type & value stored of a string variable by the hash name - // * @param _h The keccak256 hash of the variable name - // */ - // function get(bytes32 _h) public view returns (uint256 varType, string varVal){ - // //require(s[_h]._name == _h,"not found"); - // return (s[_h]._type, s[_h]._value); - // } - // /** - // * @dev Get the type stored of a string variable by the hash name - // * @param _h The keccak256 hash of the variable name - // */ - // function getType(bytes32 _h) public view returns (uint256){ - // require(s[_h]._name == _h,"not found"); - // return s[_h]._type; - // } - // /** - // * @dev Get the value stored of a string variable by the hash name - // * @param _h The keccak256 hash of the variable name - // */ - // function getValue(bytes32 _h) public view returns (string){ - // require(s[_h]._name == _h,"not found"); - // return s[_h]._value; - // } + event StringVarableChanged(bytes32 indexed _name, string _value); + + event UintVarableChanged(bytes32 indexed _name, uint _value); + + event IntVarableChanged(bytes32 indexed _name, int _value); + + event AddressVarableChanged(bytes32 indexed _name, address _value); + + event Bytes32VarableChanged(bytes32 indexed _name, bytes32 _value); + + event BytesVarableChanged(bytes32 indexed _name, bytes _value); + + event VarableChanged(bytes32 indexed _name, uint256 indexed _type, string _value); + + /** + * @dev Allows the owner to set a value for a int variable + * @param h The keccak256 hash of the variable name + * @param v The value to be stored + */ + function setInt(bytes32 h, int256 v) internal { + _setInt(h, v); + emit IntVarableChanged(h, v); + } + + /** + * @dev Allows the owner to set a value for a boolean variable + * @param h The keccak256 hash of the variable name + * @param v The value to be stored + */ + function setUint(bytes32 h, uint256 v) internal { + _setUint(h, v); + emit UintVarableChanged(h, v); + } + + /** + * @dev Allows the owner to set a value for a address variable + * @param h The keccak256 hash of the variable name + * @param v The value to be stored + */ + function setAddress(bytes32 h, address v) internal { + _setAddress(h, v); + emit AddressVarableChanged(h, v); + } + + /** + * @dev Allows the owner to set a value for a string variable + * @param h The keccak256 hash of the variable name + * @param v The value to be stored + */ + function setString(bytes32 h, string memory v) internal { + _setString(h, v); + emit StringVarableChanged(h, v); + } + + /** + * @dev Allows the owner to set a value for a bytes variable + * @param h The keccak256 hash of the variable name + * @param v The value to be stored + */ + function setBytes(bytes32 h, bytes memory v) internal { + _setBytes(h, v); + emit BytesVarableChanged(h, v); + } + + /** + * @dev Allows the owner to set a value for a bytes32 variable + * @param h The keccak256 hash of the variable name + * @param v The value to be stored + */ + function setBytes32(bytes32 h, bytes32 v) internal { + _setBytes32(h, v); + emit Bytes32VarableChanged(h, v); + } + + // mapping(bytes32 => Variable) internal s; + + // /** + // * @dev Add a new variable . + // * @param _h The keccak256 hash of the variable name + // * @param _t The type of value + // * @param _v The value to be stored + // */ + // function _add(bytes32 _h, uint256 _t, string _v) internal { + // require(s[_h]._name == "","not found"); + // s[_h] = Variable(_h,_t,_v); + // emit VarableAdded(_h,_t,_v); + // } + // /** + // * @dev Update a new variable . + // * @param _h The keccak256 hash of the variable name + // * @param _t The type of value + // * @param _v The value to be stored + // */ + // function _change(bytes32 _h, uint256 _t, string _v) internal { + // require(s[_h]._name == _h,"not found"); + // Variable storage v = s[_h]; + // v._name = _h; + // v._type = _t; + // v._value = _v; + // emit VarableChanged(_h,_t,_v); + + // } + // /** + // * @dev Get the type & value stored of a string variable by the hash name + // * @param _h The keccak256 hash of the variable name + // */ + // function get(bytes32 _h) public view returns (uint256 varType, string varVal){ + // //require(s[_h]._name == _h,"not found"); + // return (s[_h]._type, s[_h]._value); + // } + // /** + // * @dev Get the type stored of a string variable by the hash name + // * @param _h The keccak256 hash of the variable name + // */ + // function getType(bytes32 _h) public view returns (uint256){ + // require(s[_h]._name == _h,"not found"); + // return s[_h]._type; + // } + // /** + // * @dev Get the value stored of a string variable by the hash name + // * @param _h The keccak256 hash of the variable name + // */ + // function getValue(bytes32 _h) public view returns (string){ + // require(s[_h]._name == _h,"not found"); + // return s[_h]._value; + // } } diff --git a/wemix/governance-contract/contracts/abstract/AGov.sol b/wemix/governance-contract/contracts/abstract/AGov.sol index 765e5f1c480b..53d33e142cea 100644 --- a/wemix/governance-contract/contracts/abstract/AGov.sol +++ b/wemix/governance-contract/contracts/abstract/AGov.sol @@ -6,86 +6,86 @@ import "../interface/IGov.sol"; import "../GovChecker.sol"; abstract contract AGov is GovChecker, IGov { - uint public modifiedBlock; + uint public modifiedBlock; - // For voting member - mapping(uint256 => address) internal voters; - mapping(address => uint256) public voterIdx; - uint256 internal memberLength; + // For voting member + mapping(uint256 => address) internal voters; + mapping(address => uint256) public voterIdx; + uint256 internal memberLength; - // For reward member - mapping(uint256 => address) internal rewards; - mapping(address => uint256) public rewardIdx; + // For reward member + mapping(uint256 => address) internal rewards; + mapping(address => uint256) public rewardIdx; - //For staking member - mapping(uint256 => address) internal stakers; - mapping(address => uint256) public stakerIdx; + //For staking member + mapping(uint256 => address) internal stakers; + mapping(address => uint256) public stakerIdx; - //For a node duplicate check - // mainnet value is here - // mapping(bytes32=>bool) internal checkNodeInfo; - mapping(bytes => bool) internal checkNodeName; - mapping(bytes => bool) internal checkNodeEnode; - mapping(bytes32 => bool) internal checkNodeIpPort; + //For a node duplicate check + // mainnet value is here + // mapping(bytes32=>bool) internal checkNodeInfo; + mapping(bytes => bool) internal checkNodeName; + mapping(bytes => bool) internal checkNodeEnode; + mapping(bytes32 => bool) internal checkNodeIpPort; - // For enode - struct Node { - bytes name; - bytes enode; - bytes ip; - uint port; - } + // For enode + struct Node { + bytes name; + bytes enode; + bytes ip; + uint port; + } - mapping(uint256 => Node) internal nodes; - mapping(address => uint256) internal nodeIdxFromMember; - mapping(uint256 => address) internal nodeToMember; - uint256 internal nodeLength; + mapping(uint256 => Node) internal nodes; + mapping(address => uint256) internal nodeIdxFromMember; + mapping(uint256 => address) internal nodeToMember; + uint256 internal nodeLength; - // For ballot - uint256 public ballotLength; - uint256 public voteLength; - uint256 internal ballotInVoting; + // For ballot + uint256 public ballotLength; + uint256 public voteLength; + uint256 internal ballotInVoting; - function isReward(address addr) public view override returns (bool) { - return (rewardIdx[addr] != 0); - } - function isVoter(address addr) public view override returns (bool) { - return (voterIdx[addr] != 0); - } - function isStaker(address addr) public view override returns (bool) { - return (stakerIdx[addr] != 0); - } - function isMember(address addr) public view override returns (bool) { - return (isStaker(addr) || isVoter(addr)); - } - function getMember(uint256 idx) public view override returns (address) { - return stakers[idx]; - } - function getMemberLength() public view override returns (uint256) { - return memberLength; - } - function getReward(uint256 idx) public view override returns (address) { - return rewards[idx]; - } - function getNodeIdxFromMember(address addr) public view override returns (uint256) { - return nodeIdxFromMember[addr]; - } - function getMemberFromNodeIdx(uint256 idx) public view override returns (address) { - return nodeToMember[idx]; - } - function getNodeLength() public view override returns (uint256) { - return nodeLength; - } - //====NxtMeta=====/ - function getVoter(uint256 idx) public view override returns (address) { - return voters[idx]; - } + function isReward(address addr) public view override returns (bool) { + return (rewardIdx[addr] != 0); + } + function isVoter(address addr) public view override returns (bool) { + return (voterIdx[addr] != 0); + } + function isStaker(address addr) public view override returns (bool) { + return (stakerIdx[addr] != 0); + } + function isMember(address addr) public view override returns (bool) { + return (isStaker(addr) || isVoter(addr)); + } + function getMember(uint256 idx) public view override returns (address) { + return stakers[idx]; + } + function getMemberLength() public view override returns (uint256) { + return memberLength; + } + function getReward(uint256 idx) public view override returns (address) { + return rewards[idx]; + } + function getNodeIdxFromMember(address addr) public view override returns (uint256) { + return nodeIdxFromMember[addr]; + } + function getMemberFromNodeIdx(uint256 idx) public view override returns (address) { + return nodeToMember[idx]; + } + function getNodeLength() public view override returns (uint256) { + return nodeLength; + } + //====NxtMeta=====/ + function getVoter(uint256 idx) public view override returns (address) { + return voters[idx]; + } - function getNode(uint256 idx) public view override returns (bytes memory name, bytes memory enode, bytes memory ip, uint port) { - return (nodes[idx].name, nodes[idx].enode, nodes[idx].ip, nodes[idx].port); - } + function getNode(uint256 idx) public view override returns (bytes memory name, bytes memory enode, bytes memory ip, uint port) { + return (nodes[idx].name, nodes[idx].enode, nodes[idx].ip, nodes[idx].port); + } - function getBallotInVoting() public view override returns (uint256) { - return ballotInVoting; - } + function getBallotInVoting() public view override returns (uint256) { + return ballotInVoting; + } } diff --git a/wemix/governance-contract/contracts/abstract/BallotEnums.sol b/wemix/governance-contract/contracts/abstract/BallotEnums.sol index 6cabd9c33957..039983b19749 100644 --- a/wemix/governance-contract/contracts/abstract/BallotEnums.sol +++ b/wemix/governance-contract/contracts/abstract/BallotEnums.sol @@ -2,27 +2,27 @@ pragma solidity ^0.8.0; contract BallotEnums { - enum BallotStates { - Invalid, - Ready, - InProgress, - Accepted, - Rejected, - Canceled - } + enum BallotStates { + Invalid, + Ready, + InProgress, + Accepted, + Rejected, + Canceled + } - enum DecisionTypes { - Invalid, - Accept, - Reject - } + enum DecisionTypes { + Invalid, + Accept, + Reject + } - enum BallotTypes { - Invalid, - MemberAdd, // new Member Address, new Node id, new Node ip, new Node port - MemberRemoval, // old Member Address - MemberChange, // Old Member Address, New Member Address, new Node id, New Node ip, new Node port - GovernanceChange, // new Governace Impl Address - EnvValChange // Env variable name, type , value - } + enum BallotTypes { + Invalid, + MemberAdd, // new Member Address, new Node id, new Node ip, new Node port + MemberRemoval, // old Member Address + MemberChange, // Old Member Address, New Member Address, new Node id, New Node ip, new Node port + GovernanceChange, // new Governace Impl Address + EnvValChange // Env variable name, type , value + } } diff --git a/wemix/governance-contract/contracts/abstract/EnvConstants.sol b/wemix/governance-contract/contracts/abstract/EnvConstants.sol index db5026caa1cb..d779d971310a 100644 --- a/wemix/governance-contract/contracts/abstract/EnvConstants.sol +++ b/wemix/governance-contract/contracts/abstract/EnvConstants.sol @@ -4,51 +4,36 @@ pragma solidity ^0.8.0; contract EnvConstants { bytes32 public constant BLOCKS_PER_NAME = keccak256("blocksPer"); - bytes32 public constant BALLOT_DURATION_MIN_NAME = - keccak256("ballotDurationMin"); + bytes32 public constant BALLOT_DURATION_MIN_NAME = keccak256("ballotDurationMin"); - bytes32 public constant BALLOT_DURATION_MAX_NAME = - keccak256("ballotDurationMax"); + bytes32 public constant BALLOT_DURATION_MAX_NAME = keccak256("ballotDurationMax"); bytes32 public constant STAKING_MIN_NAME = keccak256("stakingMin"); bytes32 public constant STAKING_MAX_NAME = keccak256("stakingMax"); - bytes32 public constant MAX_IDLE_BLOCK_INTERVAL_NAME = - keccak256("MaxIdleBlockInterval"); + bytes32 public constant MAX_IDLE_BLOCK_INTERVAL_NAME = keccak256("MaxIdleBlockInterval"); //=======NXTMeta========/ - bytes32 public constant BALLOT_DURATION_MIN_MAX_NAME = - keccak256("ballotDurationMinMax"); + bytes32 public constant BALLOT_DURATION_MIN_MAX_NAME = keccak256("ballotDurationMinMax"); bytes32 public constant STAKING_MIN_MAX_NAME = keccak256("stakingMinMax"); - bytes32 public constant BLOCK_CREATION_TIME_NAME = - keccak256("blockCreationTime"); - bytes32 public constant BLOCK_REWARD_AMOUNT_NAME = - keccak256("blockRewardAmount"); + bytes32 public constant BLOCK_CREATION_TIME_NAME = keccak256("blockCreationTime"); + bytes32 public constant BLOCK_REWARD_AMOUNT_NAME = keccak256("blockRewardAmount"); // unit = gwei - bytes32 public constant MAX_PRIORITY_FEE_PER_GAS_NAME = - keccak256("maxPriorityFeePerGas"); - - bytes32 public constant BLOCK_REWARD_DISTRIBUTION_METHOD_NAME = - keccak256("blockRewardDistribution"); - bytes32 public constant BLOCK_REWARD_DISTRIBUTION_BLOCK_PRODUCER_NAME = - keccak256("blockRewardDistributionBlockProducer"); - bytes32 public constant BLOCK_REWARD_DISTRIBUTION_STAKING_REWARD_NAME = - keccak256("blockRewardDistributionStakingReward"); - bytes32 public constant BLOCK_REWARD_DISTRIBUTION_ECOSYSTEM_NAME = - keccak256("blockRewardDistributionEcosystem"); - bytes32 public constant BLOCK_REWARD_DISTRIBUTION_MAINTENANCE_NAME = - keccak256("blockRewardDistributionMaintenance"); - - bytes32 public constant GASLIMIT_AND_BASE_FEE_NAME = - keccak256("gasLimitAndBaseFee"); + bytes32 public constant MAX_PRIORITY_FEE_PER_GAS_NAME = keccak256("maxPriorityFeePerGas"); + + bytes32 public constant BLOCK_REWARD_DISTRIBUTION_METHOD_NAME = keccak256("blockRewardDistribution"); + bytes32 public constant BLOCK_REWARD_DISTRIBUTION_BLOCK_PRODUCER_NAME = keccak256("blockRewardDistributionBlockProducer"); + bytes32 public constant BLOCK_REWARD_DISTRIBUTION_STAKING_REWARD_NAME = keccak256("blockRewardDistributionStakingReward"); + bytes32 public constant BLOCK_REWARD_DISTRIBUTION_ECOSYSTEM_NAME = keccak256("blockRewardDistributionEcosystem"); + bytes32 public constant BLOCK_REWARD_DISTRIBUTION_MAINTENANCE_NAME = keccak256("blockRewardDistributionMaintenance"); + + bytes32 public constant GASLIMIT_AND_BASE_FEE_NAME = keccak256("gasLimitAndBaseFee"); bytes32 public constant BLOCK_GASLIMIT_NAME = keccak256("blockGasLimit"); - bytes32 public constant BASE_FEE_MAX_CHANGE_RATE_NAME = - keccak256("baseFeeMaxChangeRate"); - bytes32 public constant GAS_TARGET_PERCENTAGE_NAME = - keccak256("gasTargetPercentage"); + bytes32 public constant BASE_FEE_MAX_CHANGE_RATE_NAME = keccak256("baseFeeMaxChangeRate"); + bytes32 public constant GAS_TARGET_PERCENTAGE_NAME = keccak256("gasTargetPercentage"); bytes32 public constant MAX_BASE_FEE_NAME = keccak256("maxBaseFee"); diff --git a/wemix/governance-contract/contracts/abstract/TestnetAGov.sol b/wemix/governance-contract/contracts/abstract/TestnetAGov.sol index 22344f55ce5f..8df45ee91cc3 100644 --- a/wemix/governance-contract/contracts/abstract/TestnetAGov.sol +++ b/wemix/governance-contract/contracts/abstract/TestnetAGov.sol @@ -6,86 +6,86 @@ import "../interface/ITestnetGov.sol"; import "../GovChecker.sol"; abstract contract TestnetAGov is GovChecker, ITestnetGov { - uint public modifiedBlock; + uint public modifiedBlock; - // For voting member - mapping(uint256 => address) internal voters; - mapping(address => uint256) public voterIdx; - uint256 internal memberLength; + // For voting member + mapping(uint256 => address) internal voters; + mapping(address => uint256) public voterIdx; + uint256 internal memberLength; - // For reward member - mapping(uint256 => address) internal rewards; - mapping(address => uint256) public rewardIdx; + // For reward member + mapping(uint256 => address) internal rewards; + mapping(address => uint256) public rewardIdx; - //For staking member - mapping(uint256 => address) internal stakers; - mapping(address => uint256) public stakerIdx; + //For staking member + mapping(uint256 => address) internal stakers; + mapping(address => uint256) public stakerIdx; - //For a node duplicate check - // mainnet value is here - // mapping(bytes32=>bool) internal checkNodeInfo; - // mapping(bytes=>bool) internal checkNodeName; - // mapping(bytes=>bool) internal checkNodeEnode; - // mapping(bytes32=>bool) internal checkNodeIpPort; + //For a node duplicate check + // mainnet value is here + // mapping(bytes32=>bool) internal checkNodeInfo; + // mapping(bytes=>bool) internal checkNodeName; + // mapping(bytes=>bool) internal checkNodeEnode; + // mapping(bytes32=>bool) internal checkNodeIpPort; - // For enode - struct Node { - bytes name; - bytes enode; - bytes ip; - uint port; - } + // For enode + struct Node { + bytes name; + bytes enode; + bytes ip; + uint port; + } - mapping(uint256 => Node) internal nodes; - mapping(address => uint256) internal nodeIdxFromMember; - mapping(uint256 => address) internal nodeToMember; - uint256 internal nodeLength; + mapping(uint256 => Node) internal nodes; + mapping(address => uint256) internal nodeIdxFromMember; + mapping(uint256 => address) internal nodeToMember; + uint256 internal nodeLength; - // For ballot - uint256 public ballotLength; - uint256 public voteLength; - uint256 internal ballotInVoting; + // For ballot + uint256 public ballotLength; + uint256 public voteLength; + uint256 internal ballotInVoting; - function isReward(address addr) public view override returns (bool) { - return (rewardIdx[addr] != 0); - } - function isVoter(address addr) public view override returns (bool) { - return (voterIdx[addr] != 0); - } - function isStaker(address addr) public view override returns (bool) { - return (stakerIdx[addr] != 0); - } - function isMember(address addr) public view override returns (bool) { - return (isStaker(addr) || isVoter(addr)); - } - function getMember(uint256 idx) public view override returns (address) { - return stakers[idx]; - } - function getMemberLength() public view override returns (uint256) { - return memberLength; - } - function getReward(uint256 idx) public view override returns (address) { - return rewards[idx]; - } - function getNodeIdxFromMember(address addr) public view override returns (uint256) { - return nodeIdxFromMember[addr]; - } - function getMemberFromNodeIdx(uint256 idx) public view override returns (address) { - return nodeToMember[idx]; - } - function getNodeLength() public view override returns (uint256) { - return nodeLength; - } - //====NxtMeta=====/ - function getVoter(uint256 idx) public view override returns (address) { - return voters[idx]; - } + function isReward(address addr) public view override returns (bool) { + return (rewardIdx[addr] != 0); + } + function isVoter(address addr) public view override returns (bool) { + return (voterIdx[addr] != 0); + } + function isStaker(address addr) public view override returns (bool) { + return (stakerIdx[addr] != 0); + } + function isMember(address addr) public view override returns (bool) { + return (isStaker(addr) || isVoter(addr)); + } + function getMember(uint256 idx) public view override returns (address) { + return stakers[idx]; + } + function getMemberLength() public view override returns (uint256) { + return memberLength; + } + function getReward(uint256 idx) public view override returns (address) { + return rewards[idx]; + } + function getNodeIdxFromMember(address addr) public view override returns (uint256) { + return nodeIdxFromMember[addr]; + } + function getMemberFromNodeIdx(uint256 idx) public view override returns (address) { + return nodeToMember[idx]; + } + function getNodeLength() public view override returns (uint256) { + return nodeLength; + } + //====NxtMeta=====/ + function getVoter(uint256 idx) public view override returns (address) { + return voters[idx]; + } - function getNode(uint256 idx) public view override returns (bytes memory name, bytes memory enode, bytes memory ip, uint port) { - return (nodes[idx].name, nodes[idx].enode, nodes[idx].ip, nodes[idx].port); - } + function getNode(uint256 idx) public view override returns (bytes memory name, bytes memory enode, bytes memory ip, uint port) { + return (nodes[idx].name, nodes[idx].enode, nodes[idx].ip, nodes[idx].port); + } - function getBallotInVoting() public view override returns (uint256) { - return ballotInVoting; - } + function getBallotInVoting() public view override returns (uint256) { + return ballotInVoting; + } } diff --git a/wemix/governance-contract/contracts/interface/IBallotStorage.sol b/wemix/governance-contract/contracts/interface/IBallotStorage.sol index 3636f6b1c9cb..1af8c1fc3954 100644 --- a/wemix/governance-contract/contracts/interface/IBallotStorage.sol +++ b/wemix/governance-contract/contracts/interface/IBallotStorage.sol @@ -2,43 +2,43 @@ pragma solidity ^0.8.0; interface IBallotStorage { - function createBallotForMember( - uint256, - uint256, - uint256, - address, - address, - address, - address, - address, - bytes memory, - bytes memory, - bytes memory, - uint - ) external; + function createBallotForMember( + uint256, + uint256, + uint256, + address, + address, + address, + address, + address, + bytes memory, + bytes memory, + bytes memory, + uint + ) external; - function createBallotForAddress(uint256, uint256, uint256, address, address) external returns (uint256); - function createBallotForVariable(uint256, uint256, uint256, address, bytes32, uint256, bytes memory) external returns (uint256); - function createBallotForExit(uint256, uint256, uint256) external; - function createVote(uint256, uint256, address, uint256, uint256) external; - function finalizeBallot(uint256, uint256) external; - function startBallot(uint256, uint256, uint256) external; - function updateBallotMemo(uint256, bytes memory) external; - function updateBallotDuration(uint256, uint256) external; - function updateBallotMemberLockAmount(uint256, uint256) external; + function createBallotForAddress(uint256, uint256, uint256, address, address) external returns (uint256); + function createBallotForVariable(uint256, uint256, uint256, address, bytes32, uint256, bytes memory) external returns (uint256); + function createBallotForExit(uint256, uint256, uint256) external; + function createVote(uint256, uint256, address, uint256, uint256) external; + function finalizeBallot(uint256, uint256) external; + function startBallot(uint256, uint256, uint256) external; + function updateBallotMemo(uint256, bytes memory) external; + function updateBallotDuration(uint256, uint256) external; + function updateBallotMemberLockAmount(uint256, uint256) external; - function getBallotPeriod(uint256) external view returns (uint256, uint256, uint256); - function getBallotVotingInfo(uint256) external view returns (uint256, uint256, uint256); - function getBallotState(uint256) external view returns (uint256, uint256, bool); + function getBallotPeriod(uint256) external view returns (uint256, uint256, uint256); + function getBallotVotingInfo(uint256) external view returns (uint256, uint256, uint256); + function getBallotState(uint256) external view returns (uint256, uint256, bool); - function getBallotBasic( - uint256 - ) external view returns (uint256, uint256, uint256, address, bytes memory, uint256, uint256, uint256, uint256, bool, uint256); + function getBallotBasic( + uint256 + ) external view returns (uint256, uint256, uint256, address, bytes memory, uint256, uint256, uint256, uint256, bool, uint256); - function getBallotMember( - uint256 - ) external view returns (address, address, address, address, bytes memory, bytes memory, bytes memory, uint256, uint256); - function getBallotAddress(uint256) external view returns (address); - function getBallotVariable(uint256) external view returns (bytes32, uint256, bytes memory); - function getBallotForExit(uint256) external view returns (uint256, uint256); + function getBallotMember( + uint256 + ) external view returns (address, address, address, address, bytes memory, bytes memory, bytes memory, uint256, uint256); + function getBallotAddress(uint256) external view returns (address); + function getBallotVariable(uint256) external view returns (bytes32, uint256, bytes memory); + function getBallotForExit(uint256) external view returns (uint256, uint256); } diff --git a/wemix/governance-contract/contracts/interface/IEnvStorage.sol b/wemix/governance-contract/contracts/interface/IEnvStorage.sol index b7e5aa8fb8a1..b2ed4ce1ec92 100644 --- a/wemix/governance-contract/contracts/interface/IEnvStorage.sol +++ b/wemix/governance-contract/contracts/interface/IEnvStorage.sol @@ -2,35 +2,35 @@ pragma solidity ^0.8.0; interface IEnvStorage { - function setBlocksPerByBytes(bytes memory) external; - function setBallotDurationMinByBytes(bytes memory) external; - function setBallotDurationMaxByBytes(bytes memory) external; - function setStakingMinByBytes(bytes memory) external; - function setStakingMaxByBytes(bytes memory) external; - function setMaxIdleBlockIntervalByBytes(bytes memory) external; - function setBlockCreationTimeByBytes(bytes memory _value) external; - function setBlockRewardAmountByBytes(bytes memory _value) external; - function setMaxPriorityFeePerGasByBytes(bytes memory _value) external; - function setBallotDurationMinMax(uint256 _min, uint256 _max) external; - function setBlockRewardDistributionMethodByBytes(bytes memory _value) external; - function setGasLimitAndBaseFeeByBytes(bytes memory _value) external; - function setMaxBaseFeeByBytes(bytes memory _value) external; - function setBallotDurationMinMaxByBytes(bytes memory _value) external; - function setStakingMinMaxByBytes(bytes memory _value) external; - function getBlockCreationTime() external view returns (uint256); - function getBlockRewardAmount() external view returns (uint256); - function getMaxPriorityFeePerGas() external view returns (uint256); - function getStakingMinMax() external view returns (uint256, uint256); - function getBlockRewardDistributionMethod() external view returns (uint256, uint256, uint256, uint256); - function getGasLimitAndBaseFee() external view returns (uint256, uint256, uint256); - function getMaxBaseFee() external view returns (uint256); - function getBlocksPer() external view returns (uint256); - function getStakingMin() external view returns (uint256); - function getStakingMax() external view returns (uint256); - function getBallotDurationMin() external view returns (uint256); - function getBallotDurationMax() external view returns (uint256); - function getBallotDurationMinMax() external view returns (uint256, uint256); - function getMaxIdleBlockInterval() external view returns (uint256); - function checkVariableCondition(bytes32 envKey, bytes memory envVal) external pure returns (bool); - function setVariable(bytes32 envKey, bytes memory envVal) external; + function setBlocksPerByBytes(bytes memory) external; + function setBallotDurationMinByBytes(bytes memory) external; + function setBallotDurationMaxByBytes(bytes memory) external; + function setStakingMinByBytes(bytes memory) external; + function setStakingMaxByBytes(bytes memory) external; + function setMaxIdleBlockIntervalByBytes(bytes memory) external; + function setBlockCreationTimeByBytes(bytes memory _value) external; + function setBlockRewardAmountByBytes(bytes memory _value) external; + function setMaxPriorityFeePerGasByBytes(bytes memory _value) external; + function setBallotDurationMinMax(uint256 _min, uint256 _max) external; + function setBlockRewardDistributionMethodByBytes(bytes memory _value) external; + function setGasLimitAndBaseFeeByBytes(bytes memory _value) external; + function setMaxBaseFeeByBytes(bytes memory _value) external; + function setBallotDurationMinMaxByBytes(bytes memory _value) external; + function setStakingMinMaxByBytes(bytes memory _value) external; + function getBlockCreationTime() external view returns (uint256); + function getBlockRewardAmount() external view returns (uint256); + function getMaxPriorityFeePerGas() external view returns (uint256); + function getStakingMinMax() external view returns (uint256, uint256); + function getBlockRewardDistributionMethod() external view returns (uint256, uint256, uint256, uint256); + function getGasLimitAndBaseFee() external view returns (uint256, uint256, uint256); + function getMaxBaseFee() external view returns (uint256); + function getBlocksPer() external view returns (uint256); + function getStakingMin() external view returns (uint256); + function getStakingMax() external view returns (uint256); + function getBallotDurationMin() external view returns (uint256); + function getBallotDurationMax() external view returns (uint256); + function getBallotDurationMinMax() external view returns (uint256, uint256); + function getMaxIdleBlockInterval() external view returns (uint256); + function checkVariableCondition(bytes32 envKey, bytes memory envVal) external pure returns (bool); + function setVariable(bytes32 envKey, bytes memory envVal) external; } diff --git a/wemix/governance-contract/contracts/interface/IGov.sol b/wemix/governance-contract/contracts/interface/IGov.sol index c223e232a592..3d2c2e522f1b 100644 --- a/wemix/governance-contract/contracts/interface/IGov.sol +++ b/wemix/governance-contract/contracts/interface/IGov.sol @@ -2,18 +2,18 @@ pragma solidity ^0.8.0; interface IGov { - function isReward(address addr) external view returns (bool); - function isVoter(address addr) external view returns (bool); - function isStaker(address addr) external view returns (bool); - function isMember(address) external view returns (bool); - function getMember(uint256) external view returns (address); - function getMemberLength() external view returns (uint256); - function getReward(uint256) external view returns (address); - function getNodeIdxFromMember(address) external view returns (uint256); - function getMemberFromNodeIdx(uint256) external view returns (address); - function getNodeLength() external view returns (uint256); - function getNode(uint256) external view returns (bytes memory, bytes memory, bytes memory, uint); - function getBallotInVoting() external view returns (uint256); - function getVoter(uint256 idx) external view returns (address); - function initMigration(address registry, uint256 oldModifiedBlock, address oldOwner) external; + function isReward(address addr) external view returns (bool); + function isVoter(address addr) external view returns (bool); + function isStaker(address addr) external view returns (bool); + function isMember(address) external view returns (bool); + function getMember(uint256) external view returns (address); + function getMemberLength() external view returns (uint256); + function getReward(uint256) external view returns (address); + function getNodeIdxFromMember(address) external view returns (uint256); + function getMemberFromNodeIdx(uint256) external view returns (address); + function getNodeLength() external view returns (uint256); + function getNode(uint256) external view returns (bytes memory, bytes memory, bytes memory, uint); + function getBallotInVoting() external view returns (uint256); + function getVoter(uint256 idx) external view returns (address); + function initMigration(address registry, uint256 oldModifiedBlock, address oldOwner) external; } diff --git a/wemix/governance-contract/contracts/interface/IGovStaking.sol b/wemix/governance-contract/contracts/interface/IGovStaking.sol index 3fe18f9e663d..15d30e4210b3 100644 --- a/wemix/governance-contract/contracts/interface/IGovStaking.sol +++ b/wemix/governance-contract/contracts/interface/IGovStaking.sol @@ -2,5 +2,5 @@ pragma solidity ^0.8.0; interface IGovStaking { - function ncpStaking() external view returns (address); + function ncpStaking() external view returns (address); } diff --git a/wemix/governance-contract/contracts/interface/INCPExit.sol b/wemix/governance-contract/contracts/interface/INCPExit.sol index 0c1c99e36d6a..7be58769f619 100644 --- a/wemix/governance-contract/contracts/interface/INCPExit.sol +++ b/wemix/governance-contract/contracts/interface/INCPExit.sol @@ -1,43 +1,42 @@ // SPDX-License-Identifier: MIT - pragma solidity ^0.8.0; interface INCPExit { - /** - * @dev Sets a new administrator. - * @param _newAdministrator Address of the new administrator. - */ - function setAdministrator(address _newAdministrator) external; - - /** - * @dev Sets a new administrator setter. - * @param _newAdministratorSetter Address of the new administrator setter. - */ - function setAdministratorSetter(address _newAdministratorSetter) external; - - /** - * @dev Exits from the contract. - * @param exitNcp Address of the NCP to exit. - * @param totalAmount Total amount of ether to exit with. - * @param lockedUserBalanceToNCPTotal Total locked user balance to NCP. - */ - function depositExitAmount(address exitNcp, uint256 totalAmount, uint256 lockedUserBalanceToNCPTotal) external payable; - - /** - * @dev Withdraws amount for a user. - * @param exitNcp Address of the ncp - * @param exitUser Address of the user to withdraw for. - * @param amount Amount to withdraw. - */ - function withdrawForUser(address exitNcp, address exitUser, uint256 amount) external; - - /** - * @dev Withdraws amount for the administrator. - * @param exitNcp Address of the NCP to withdraw from. - */ - function withdrawForAdministrator(address exitNcp, uint256 amount, address to) external; - - function getAvailableAmountForAdministrator(address exitNcp) external view returns (uint256); - - function getLockedUserBalanceToNCPTotal(address exitNcp) external view returns (uint256); + /** + * @dev Sets a new administrator. + * @param _newAdministrator Address of the new administrator. + */ + function setAdministrator(address _newAdministrator) external; + + /** + * @dev Sets a new administrator setter. + * @param _newAdministratorSetter Address of the new administrator setter. + */ + function setAdministratorSetter(address _newAdministratorSetter) external; + + /** + * @dev Exits from the contract. + * @param exitNcp Address of the NCP to exit. + * @param totalAmount Total amount of ether to exit with. + * @param lockedUserBalanceToNCPTotal Total locked user balance to NCP. + */ + function depositExitAmount(address exitNcp, uint256 totalAmount, uint256 lockedUserBalanceToNCPTotal) external payable; + + /** + * @dev Withdraws amount for a user. + * @param exitNcp Address of the ncp + * @param exitUser Address of the user to withdraw for. + * @param amount Amount to withdraw. + */ + function withdrawForUser(address exitNcp, address exitUser, uint256 amount) external; + + /** + * @dev Withdraws amount for the administrator. + * @param exitNcp Address of the NCP to withdraw from. + */ + function withdrawForAdministrator(address exitNcp, uint256 amount, address to) external; + + function getAvailableAmountForAdministrator(address exitNcp) external view returns (uint256); + + function getLockedUserBalanceToNCPTotal(address exitNcp) external view returns (uint256); } diff --git a/wemix/governance-contract/contracts/interface/INCPStaking.sol b/wemix/governance-contract/contracts/interface/INCPStaking.sol index fb34f900beff..1ba588cead5b 100644 --- a/wemix/governance-contract/contracts/interface/INCPStaking.sol +++ b/wemix/governance-contract/contracts/interface/INCPStaking.sol @@ -4,15 +4,15 @@ pragma solidity ^0.8.0; /// @author @seunghwalee interface INCPStaking { - struct UserInfo { - uint256 amount; - uint256 rewardDebt; - uint256 pendingReward; - uint256 pendingAmountReward; - uint256 lastRewardClaimed; - } - function ncpDeposit(uint256 amount, address payable to) external payable; - function ncpWithdraw(uint256 amount, address payable to) external payable; - function getUserInfo(uint256 pid, address account) external view returns (UserInfo memory info); - function ncpToIdx(address ncp) external view returns (uint256); + struct UserInfo { + uint256 amount; + uint256 rewardDebt; + uint256 pendingReward; + uint256 pendingAmountReward; + uint256 lastRewardClaimed; + } + function ncpDeposit(uint256 amount, address payable to) external payable; + function ncpWithdraw(uint256 amount, address payable to) external payable; + function getUserInfo(uint256 pid, address account) external view returns (UserInfo memory info); + function ncpToIdx(address ncp) external view returns (uint256); } diff --git a/wemix/governance-contract/contracts/interface/IRegistry.sol b/wemix/governance-contract/contracts/interface/IRegistry.sol index db0d31479ef8..6645818d06a7 100644 --- a/wemix/governance-contract/contracts/interface/IRegistry.sol +++ b/wemix/governance-contract/contracts/interface/IRegistry.sol @@ -2,5 +2,5 @@ pragma solidity ^0.8.0; interface IRegistry { - function getContractAddress(bytes32) external view returns (address); + function getContractAddress(bytes32) external view returns (address); } diff --git a/wemix/governance-contract/contracts/interface/IStaking.sol b/wemix/governance-contract/contracts/interface/IStaking.sol index a59cd54216d0..07ed6c7337b1 100644 --- a/wemix/governance-contract/contracts/interface/IStaking.sol +++ b/wemix/governance-contract/contracts/interface/IStaking.sol @@ -2,21 +2,21 @@ pragma solidity ^0.8.0; interface IStaking { - function deposit() external payable; - function withdraw(uint256) external; - function lock(address, uint256) external; - function unlock(address, uint256) external; - function transferLocked(address, uint256, uint256) external; - function balanceOf(address) external view returns (uint256); - function lockedBalanceOf(address) external view returns (uint256); - function availableBalanceOf(address) external view returns (uint256); - function calcVotingWeight(address) external view returns (uint256); - function calcVotingWeightWithScaleFactor(address, uint32) external view returns (uint256); - // function isAllowed(address voter, address staker) external view returns(bool); - function userBalanceOf(address ncp, address user) external view returns (uint256); - function userTotalBalanceOf(address ncp) external view returns (uint256); - function getRatioOfUserBalance(address ncp) external view returns (uint256); - function delegateDepositAndLockMore(address ncp) external payable; - function delegateUnlockAndWithdraw(address ncp, uint256 amount) external; - function getTotalLockedBalance() external view returns (uint256); + function deposit() external payable; + function withdraw(uint256) external; + function lock(address, uint256) external; + function unlock(address, uint256) external; + function transferLocked(address, uint256, uint256) external; + function balanceOf(address) external view returns (uint256); + function lockedBalanceOf(address) external view returns (uint256); + function availableBalanceOf(address) external view returns (uint256); + function calcVotingWeight(address) external view returns (uint256); + function calcVotingWeightWithScaleFactor(address, uint32) external view returns (uint256); + // function isAllowed(address voter, address staker) external view returns(bool); + function userBalanceOf(address ncp, address user) external view returns (uint256); + function userTotalBalanceOf(address ncp) external view returns (uint256); + function getRatioOfUserBalance(address ncp) external view returns (uint256); + function delegateDepositAndLockMore(address ncp) external payable; + function delegateUnlockAndWithdraw(address ncp, uint256 amount) external; + function getTotalLockedBalance() external view returns (uint256); } diff --git a/wemix/governance-contract/contracts/interface/ITestnetGov.sol b/wemix/governance-contract/contracts/interface/ITestnetGov.sol index b5cc0a502705..c84e5e9d73ac 100644 --- a/wemix/governance-contract/contracts/interface/ITestnetGov.sol +++ b/wemix/governance-contract/contracts/interface/ITestnetGov.sol @@ -2,17 +2,17 @@ pragma solidity ^0.8.0; interface ITestnetGov { - function isReward(address addr) external view returns (bool); - function isVoter(address addr) external view returns (bool); - function isStaker(address addr) external view returns (bool); - function isMember(address) external view returns (bool); - function getMember(uint256) external view returns (address); - function getMemberLength() external view returns (uint256); - function getReward(uint256) external view returns (address); - function getNodeIdxFromMember(address) external view returns (uint256); - function getMemberFromNodeIdx(uint256) external view returns (address); - function getNodeLength() external view returns (uint256); - function getNode(uint256) external view returns (bytes memory, bytes memory, bytes memory, uint); - function getBallotInVoting() external view returns (uint256); - function getVoter(uint256 idx) external view returns (address); + function isReward(address addr) external view returns (bool); + function isVoter(address addr) external view returns (bool); + function isStaker(address addr) external view returns (bool); + function isMember(address) external view returns (bool); + function getMember(uint256) external view returns (address); + function getMemberLength() external view returns (uint256); + function getReward(uint256) external view returns (address); + function getNodeIdxFromMember(address) external view returns (uint256); + function getMemberFromNodeIdx(uint256) external view returns (address); + function getNodeLength() external view returns (uint256); + function getNode(uint256) external view returns (bytes memory, bytes memory, bytes memory, uint); + function getBallotInVoting() external view returns (uint256); + function getVoter(uint256 idx) external view returns (address); } diff --git a/wemix/governance-contract/contracts/storage/BallotStorage.sol b/wemix/governance-contract/contracts/storage/BallotStorage.sol index 825d2434b757..09151ee2e92b 100644 --- a/wemix/governance-contract/contracts/storage/BallotStorage.sol +++ b/wemix/governance-contract/contracts/storage/BallotStorage.sol @@ -5,9 +5,9 @@ import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "@openzeppelin/contracts/proxy/beacon/IBeacon.sol"; contract BallotStorage is ERC1967Proxy, IBeacon { - constructor(address _imp) ERC1967Proxy(_imp, "") {} + constructor(address _imp) ERC1967Proxy(_imp, "") {} - function implementation() external view override returns (address) { - return _implementation(); - } + function implementation() external view override returns (address) { + return _implementation(); + } } diff --git a/wemix/governance-contract/contracts/storage/BallotStorageImp.sol b/wemix/governance-contract/contracts/storage/BallotStorageImp.sol index 9c82e476d381..d0861c1d8cfa 100644 --- a/wemix/governance-contract/contracts/storage/BallotStorageImp.sol +++ b/wemix/governance-contract/contracts/storage/BallotStorageImp.sol @@ -8,563 +8,563 @@ import "../interface/IBallotStorage.sol"; import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; contract BallotStorageImp is GovChecker, BallotEnums, IBallotStorage, UUPSUpgradeable { - struct BallotBasic { - //Ballot ID - uint256 id; - //시작 시간 - uint256 startTime; - //종료 시간 - uint256 endTime; - // 투표 종류 - uint256 ballotType; - // 제안자 - address creator; - // 투표 내용 - bytes memo; - //총 투표자수 - uint256 totalVoters; - // 진행상태 - uint256 powerOfAccepts; - // 진행상태 - uint256 powerOfRejects; - // 상태 - uint256 state; - // 완료유무 - bool isFinalized; - // 투표 기간 - uint256 duration; - } - - //For MemberAdding/MemberRemoval/MemberSwap - struct BallotMember { - uint256 id; - address oldStakerAddress; - address newStakerAddress; - address newVoterAddress; - address newRewardAddress; - bytes newNodeName; // name - bytes newNodeId; // admin.nodeInfo.id is 512 bit public key - bytes newNodeIp; - uint256 newNodePort; - uint256 lockAmount; - } - - //For GovernanceChange - struct BallotAddress { - uint256 id; - address newGovernanceAddress; - } - - //For EnvValChange - struct BallotVariable { - //Ballot ID - uint256 id; - bytes32 envVariableName; - uint256 envVariableType; - bytes envVariableValue; - } - - struct BallotExit { - // For exit - uint256 unlockAmount; - uint256 slashing; - } - - struct Vote { - uint256 voteId; - uint256 ballotId; - address voter; - uint256 decision; - uint256 power; - uint256 time; - } - - event BallotCreated(uint256 indexed ballotId, uint256 indexed ballotType, address indexed creator); - - event BallotStarted(uint256 indexed ballotId, uint256 indexed startTime, uint256 indexed endTime); - - event Voted(uint256 indexed voteid, uint256 indexed ballotId, address indexed voter, uint256 decision); - - event BallotFinalized(uint256 indexed ballotId, uint256 state); - - event BallotCanceled(uint256 indexed ballotId); - - event BallotUpdated(uint256 indexed ballotId, address indexed updatedBy); - - event SetPrevBallotStorage(address indexed previous); - - mapping(uint => BallotBasic) internal ballotBasicMap; - mapping(uint => BallotMember) internal ballotMemberMap; - mapping(uint => BallotAddress) internal ballotAddressMap; - mapping(uint => BallotVariable) internal ballotVariableMap; - - mapping(uint => Vote) internal voteMap; - mapping(uint => mapping(address => bool)) internal hasVotedMap; - - address internal previousBallotStorage; - - uint256 internal ballotCount; - - // For exit - mapping(uint => BallotExit) internal ballotExitMap; - - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - _disableInitializers(); - } - function initialize(address _registry) external initializer { - __Ownable_init(); - setRegistry(_registry); - } - - modifier onlyValidTime(uint256 _startTime, uint256 _endTime) { - require(_startTime > 0 && _endTime > 0, "start or end is 0"); - require(_endTime > _startTime, "start >= end"); // && _startTime > getTime() - //uint256 diffTime = _endTime.sub(_startTime); - // require(diffTime > minBallotDuration()); - // require(diffTime <= maxBallotDuration()); - _; - } - - modifier onlyValidDuration(uint256 _duration) { - require(getMinVotingDuration() <= _duration, "Under min value of duration"); - require(_duration <= getMaxVotingDuration(), "Over max value of duration"); - _; - } - - modifier onlyGovOrCreator(uint256 _ballotId) { - require((getGovAddress() == msg.sender) || (ballotBasicMap[_ballotId].creator == msg.sender), "No Permission"); - _; - } - - modifier notDisabled() { - require(address(this) == getBallotStorageAddress(), "Is Disabled"); - _; - } - - function getMinVotingDuration() public view returns (uint256) { - return IEnvStorage(getEnvStorageAddress()).getBallotDurationMin(); - } - - function getMaxVotingDuration() public view returns (uint256) { - return IEnvStorage(getEnvStorageAddress()).getBallotDurationMax(); - } - - function getTime() public view returns (uint256) { - return block.timestamp; - } - - function getPreviousBallotStorage() public view returns (address) { - return previousBallotStorage; - } - - function isDisabled() public view returns (bool) { - return (address(this) != getBallotStorageAddress()); - } - - function getBallotCount() public view returns (uint256) { - return ballotCount; - } - - function getBallotBasic( - uint256 _id - ) - public - view - override - returns ( - uint256 startTime, - uint256 endTime, - uint256 ballotType, - address creator, - bytes memory memo, - uint256 totalVoters, - uint256 powerOfAccepts, - uint256 powerOfRejects, - uint256 state, - bool isFinalized, - uint256 duration - ) - { - BallotBasic memory tBallot = ballotBasicMap[_id]; - startTime = tBallot.startTime; - endTime = tBallot.endTime; - ballotType = tBallot.ballotType; - creator = tBallot.creator; - memo = tBallot.memo; - totalVoters = tBallot.totalVoters; - powerOfAccepts = tBallot.powerOfAccepts; - powerOfRejects = tBallot.powerOfRejects; - state = tBallot.state; - isFinalized = tBallot.isFinalized; - duration = tBallot.duration; - } - - function getBallotMember( - uint256 _id - ) - public - view - override - returns ( - address oldStakerAddress, - address newStakerAddress, - address newVoterAddress, - address newRewardAddress, - bytes memory newNodeName, // name - bytes memory newNodeId, // admin.nodeInfo.id is 512 bit public key - bytes memory newNodeIp, - uint256 newNodePort, - uint256 lockAmount - ) - { - BallotMember storage tBallot = ballotMemberMap[_id]; - oldStakerAddress = tBallot.oldStakerAddress; - newStakerAddress = tBallot.newStakerAddress; - newVoterAddress = tBallot.newVoterAddress; - newRewardAddress = tBallot.newRewardAddress; - newNodeName = tBallot.newNodeName; - newNodeId = tBallot.newNodeId; - newNodeIp = tBallot.newNodeIp; - newNodePort = tBallot.newNodePort; - lockAmount = tBallot.lockAmount; - } - - function getBallotAddress(uint256 _id) public view override returns (address newGovernanceAddress) { - BallotAddress storage tBallot = ballotAddressMap[_id]; - newGovernanceAddress = tBallot.newGovernanceAddress; - } - - function getBallotVariable( - uint256 _id - ) public view override returns (bytes32 envVariableName, uint256 envVariableType, bytes memory envVariableValue) { - BallotVariable storage tBallot = ballotVariableMap[_id]; - envVariableName = tBallot.envVariableName; - envVariableType = tBallot.envVariableType; - envVariableValue = tBallot.envVariableValue; - } - - function setPreviousBallotStorage(address _address) public onlyOwner { - require(_address != address(0), "Invalid address"); - previousBallotStorage = _address; - emit SetPrevBallotStorage(_address); - } - - //For MemberAdding/MemberRemoval/MemberSwap - function createBallotForMember( - uint256 _id, - uint256 _ballotType, - uint256 _duration, - address _creator, - address _oldStakerAddress, - address _newStakerAddress, - address _newVoterAddress, - address _newRewardAddress, - bytes memory _newNodeName, // name - bytes memory _newNodeId, // admin.nodeInfo.id is 512 bit public key - bytes memory _newNodeIp, - uint _newNodePort - ) public override onlyGov notDisabled { - require( - _areMemberBallotParamValid( - _ballotType, - _oldStakerAddress, - _newStakerAddress, - _newVoterAddress, - _newRewardAddress, - _newNodeName, - _newNodeId, - _newNodeIp, - _newNodePort - ), - "Invalid Parameter" - ); - _createBallot(_id, _ballotType, _duration, _creator); - BallotMember memory newBallot; - newBallot.id = _id; - newBallot.oldStakerAddress = _oldStakerAddress; - newBallot.newStakerAddress = _newStakerAddress; - newBallot.newVoterAddress = _newVoterAddress; - newBallot.newRewardAddress = _newRewardAddress; - newBallot.newNodeName = _newNodeName; - newBallot.newNodeId = _newNodeId; - newBallot.newNodeIp = _newNodeIp; - newBallot.newNodePort = _newNodePort; - - ballotMemberMap[_id] = newBallot; - } - - function createBallotForExit(uint256 _id, uint256 _unlockAmount, uint256 _slashing) public override onlyGov notDisabled { - ballotExitMap[_id].unlockAmount = _unlockAmount; - ballotExitMap[_id].slashing = _slashing; - } - function getBallotForExit(uint256 _id) public view override returns (uint256 unlockAmount, uint256 slashing) { - unlockAmount = ballotExitMap[_id].unlockAmount; - slashing = ballotExitMap[_id].slashing; - } - - function createBallotForAddress( - uint256 _id, - uint256 _ballotType, - uint256 _duration, - address _creator, - address _newGovernanceAddress - ) public override onlyGov notDisabled returns (uint256) { - require(_ballotType == uint256(BallotTypes.GovernanceChange), "Invalid Ballot Type"); - require(_newGovernanceAddress != address(0), "Invalid Parameter"); - _createBallot(_id, _ballotType, _duration, _creator); - BallotAddress memory newBallot; - newBallot.id = _id; - newBallot.newGovernanceAddress = _newGovernanceAddress; - ballotAddressMap[_id] = newBallot; - return _id; - } - - function createBallotForVariable( - uint256 _id, - uint256 _ballotType, - uint256 _duration, - address _creator, - bytes32 _envVariableName, - uint256 _envVariableType, - bytes memory _envVariableValue - ) public override onlyGov notDisabled returns (uint256) { - require(_areVariableBallotParamValid(_ballotType, _envVariableName, _envVariableValue), "Invalid Parameter"); - _createBallot(_id, _ballotType, _duration, _creator); - BallotVariable memory newBallot; - newBallot.id = _id; - newBallot.envVariableName = _envVariableName; - newBallot.envVariableType = _envVariableType; - newBallot.envVariableValue = _envVariableValue; - ballotVariableMap[_id] = newBallot; - return _id; - } - - function createVote(uint256 _voteId, uint256 _ballotId, address _voter, uint256 _decision, uint256 _power) public override onlyGov notDisabled { - // Check decision type - require((_decision == uint256(DecisionTypes.Accept)) || (_decision == uint256(DecisionTypes.Reject)), "Invalid decision"); - // Check if ballot exists - require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); - // Check if vote exists - require(voteMap[_voteId].voteId != _voteId, "already existed voteId"); - // Check if voted - require(!hasVotedMap[_ballotId][_voter], "already voted"); - require(ballotBasicMap[_ballotId].state == uint256(BallotStates.InProgress), "Not InProgress State"); - - voteMap[_voteId] = Vote(_voteId, _ballotId, _voter, _decision, _power, getTime()); - _updateBallotForVote(_ballotId, _voter, _decision, _power); - - emit Voted(_voteId, _ballotId, _voter, _decision); - } - - function startBallot( - uint256 _ballotId, - uint256 _startTime, - uint256 _endTime - ) public override onlyGov notDisabled onlyValidTime(_startTime, _endTime) { - require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); - require(ballotBasicMap[_ballotId].isFinalized == false, "already finalized"); - require(ballotBasicMap[_ballotId].state == uint256(BallotStates.Ready), "Not Ready State"); - - BallotBasic storage _ballot = ballotBasicMap[_ballotId]; - _ballot.startTime = _startTime; - _ballot.endTime = _endTime; - _ballot.state = uint256(BallotStates.InProgress); - emit BallotStarted(_ballotId, _startTime, _endTime); - } - - function updateBallotMemo(uint256 _ballotId, bytes memory _memo) public override onlyGovOrCreator(_ballotId) notDisabled { - require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); - require(ballotBasicMap[_ballotId].isFinalized == false, "already finalized"); - BallotBasic storage _ballot = ballotBasicMap[_ballotId]; - _ballot.memo = _memo; - emit BallotUpdated(_ballotId, msg.sender); - } - - function updateBallotDuration( - uint256 _ballotId, - uint256 _duration - ) public override onlyGovOrCreator(_ballotId) notDisabled onlyValidDuration(_duration) { - require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); - require(ballotBasicMap[_ballotId].isFinalized == false, "already finalized"); - require(ballotBasicMap[_ballotId].state == uint256(BallotStates.Ready), "Not Ready State"); - - BallotBasic storage _ballot = ballotBasicMap[_ballotId]; - _ballot.duration = _duration; - emit BallotUpdated(_ballotId, msg.sender); - } - - function updateBallotMemberLockAmount(uint256 _ballotId, uint256 _lockAmount) public override onlyGov notDisabled { - require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); - require(ballotMemberMap[_ballotId].id == _ballotId, "not existed BallotMember"); - require(ballotBasicMap[_ballotId].isFinalized == false, "already finalized"); - require(ballotBasicMap[_ballotId].state == uint256(BallotStates.Ready), "Not Ready State"); - BallotMember storage _ballot = ballotMemberMap[_ballotId]; - _ballot.lockAmount = _lockAmount; - emit BallotUpdated(_ballotId, msg.sender); - } - - // cancel ballot info - function cancelBallot(uint256 _ballotId) public onlyGovOrCreator(_ballotId) notDisabled { - require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); - require(ballotBasicMap[_ballotId].isFinalized == false, "already finalized"); - - require(ballotBasicMap[_ballotId].state == uint256(BallotStates.Ready), "Not Ready State"); - BallotBasic storage _ballot = ballotBasicMap[_ballotId]; - _ballot.state = uint256(BallotStates.Canceled); - emit BallotCanceled(_ballotId); - } - - // finalize ballot info - function finalizeBallot(uint256 _ballotId, uint256 _ballotState) public override onlyGov notDisabled { - require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); - require(ballotBasicMap[_ballotId].isFinalized == false, "already finalized"); - require((_ballotState == uint256(BallotStates.Accepted)) || (_ballotState == uint256(BallotStates.Rejected)), "Invalid Ballot State"); - - BallotBasic storage _ballot = ballotBasicMap[_ballotId]; - _ballot.state = _ballotState; - _ballot.isFinalized = true; - emit BallotFinalized(_ballotId, _ballotState); - } - - function hasAlreadyVoted(uint56 _ballotId, address _voter) public view returns (bool) { - return hasVotedMap[_ballotId][_voter]; - } - - function getVote( - uint256 _voteId - ) public view returns (uint256 voteId, uint256 ballotId, address voter, uint256 decision, uint256 power, uint256 time) { - require(voteMap[_voteId].voteId == _voteId, "not existed voteId"); - Vote memory _vote = voteMap[_voteId]; - voteId = _vote.voteId; - ballotId = _vote.ballotId; - voter = _vote.voter; - decision = _vote.decision; - power = _vote.power; - time = _vote.time; - } - - function getBallotPeriod(uint256 _id) public view override returns (uint256 startTime, uint256 endTime, uint256 duration) { - BallotBasic memory tBallot = ballotBasicMap[_id]; - startTime = tBallot.startTime; - endTime = tBallot.endTime; - duration = tBallot.duration; - } - - function getBallotVotingInfo(uint256 _id) public view override returns (uint256 totalVoters, uint256 powerOfAccepts, uint256 powerOfRejects) { - BallotBasic memory tBallot = ballotBasicMap[_id]; - totalVoters = tBallot.totalVoters; - powerOfAccepts = tBallot.powerOfAccepts; - powerOfRejects = tBallot.powerOfRejects; - } - - function getBallotState(uint256 _id) public view override returns (uint256 ballotType, uint256 state, bool isFinalized) { - BallotBasic memory tBallot = ballotBasicMap[_id]; - ballotType = tBallot.ballotType; - state = tBallot.state; - isFinalized = tBallot.isFinalized; - } - - function _createBallot(uint256 _id, uint256 _ballotType, uint256 _duration, address _creator) internal onlyValidDuration(_duration) { - require(ballotBasicMap[_id].id != _id, "Already existed ballot"); - - BallotBasic memory newBallot; - newBallot.id = _id; - newBallot.ballotType = _ballotType; - newBallot.creator = _creator; - // newBallot.memo = _memo; - newBallot.state = uint256(BallotStates.Ready); - newBallot.isFinalized = false; - newBallot.duration = _duration; - ballotBasicMap[_id] = newBallot; - ballotCount = ballotCount + 1; - emit BallotCreated(_id, _ballotType, _creator); - } - - function _areMemberBallotParamValid( - uint256 _ballotType, - address _oldStakerAddress, - address _newStakerAddress, - address _newVoterAddress, - address _newRewardAddress, - bytes memory _newName, - bytes memory _newNodeId, // admin.nodeInfo.id is 512 bit public key - bytes memory _newNodeIp, - uint _newNodePort - ) internal pure returns (bool) { - require((_ballotType >= uint256(BallotTypes.MemberAdd)) && (_ballotType <= uint256(BallotTypes.MemberChange)), "Invalid Ballot Type"); - - if (_ballotType == uint256(BallotTypes.MemberRemoval)) { - require(_oldStakerAddress != address(0), "Invalid old staker address"); - require(_newStakerAddress == address(0), "Invalid new staker address"); - require(_newVoterAddress == address(0), "Invalid new voter address"); - require(_newRewardAddress == address(0), "Invalid new reward address"); - require(_newName.length == 0, "Invalid new node name"); - require(_newNodeId.length == 0, "Invalid new node id"); - require(_newNodeIp.length == 0, "Invalid new node IP"); - require(_newNodePort == 0, "Invalid new node Port"); - } else { - require(_newName.length > 0, "Invalid new node name"); - require(_newNodeId.length == 64, "Invalid new node id"); - require(_newNodeIp.length > 0, "Invalid new node IP"); - require(_newNodePort > 0, "Invalid new node Port"); - if (_ballotType == uint256(BallotTypes.MemberAdd)) { - require(_oldStakerAddress == address(0), "Invalid old staker address"); - require(_newStakerAddress != address(0), "Invalid new staker address"); - require(_newVoterAddress != address(0), "Invalid new voter address"); - require(_newRewardAddress != address(0), "Invalid new reward address"); - } else if (_ballotType == uint256(BallotTypes.MemberChange)) { - require(_oldStakerAddress != address(0), "Invalid old staker address"); - require(_newStakerAddress != address(0), "Invalid new staker address"); - require(_newVoterAddress != address(0), "Invalid new voter address"); - require(_newRewardAddress != address(0), "Invalid new reward address"); - } - } - - return true; - } - - function _areVariableBallotParamValid( - uint256 _ballotType, - bytes32 _envVariableName, - bytes memory _envVariableValue - ) internal pure returns (bool) { - require(_ballotType == uint256(BallotTypes.EnvValChange), "Invalid Ballot Type"); - require(_envVariableName > 0, "Invalid environment variable name"); - require(_envVariableValue.length > 0, "Invalid environment variable value"); - - return true; - } - - // update ballot - function _updateBallotForVote(uint256 _ballotId, address _voter, uint256 _decision, uint256 _power) internal { - // c1. actionType 범위 - require((_decision == uint256(DecisionTypes.Accept)) || (_decision == uint256(DecisionTypes.Reject)), "Invalid decision"); - // c2. ballotId 존재 하는지 확인 - require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); - // c3. 이미 vote 했는지 확인 - require(hasVotedMap[_ballotId][_voter] == false, "already voted"); - - //1.get ballotBasic - BallotBasic storage _ballot = ballotBasicMap[_ballotId]; - //2. 투표 여부 등록 - hasVotedMap[_ballotId][_voter] = true; - //3. update totalVoters - _ballot.totalVoters = _ballot.totalVoters + 1; - //4. Update power of accept/reject - if (_decision == uint256(DecisionTypes.Accept)) { - _ballot.powerOfAccepts = _ballot.powerOfAccepts + _power; - } else { - _ballot.powerOfRejects = _ballot.powerOfRejects + _power; - } - } - - function upgradeBallotStorage(address newImp) external onlyOwner { - if (newImp != address(0)) { - _authorizeUpgrade(newImp); - _upgradeToAndCallUUPS(newImp, new bytes(0), false); - } - } - - function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} + struct BallotBasic { + //Ballot ID + uint256 id; + //시작 시간 + uint256 startTime; + //종료 시간 + uint256 endTime; + // 투표 종류 + uint256 ballotType; + // 제안자 + address creator; + // 투표 내용 + bytes memo; + //총 투표자수 + uint256 totalVoters; + // 진행상태 + uint256 powerOfAccepts; + // 진행상태 + uint256 powerOfRejects; + // 상태 + uint256 state; + // 완료유무 + bool isFinalized; + // 투표 기간 + uint256 duration; + } + + //For MemberAdding/MemberRemoval/MemberSwap + struct BallotMember { + uint256 id; + address oldStakerAddress; + address newStakerAddress; + address newVoterAddress; + address newRewardAddress; + bytes newNodeName; // name + bytes newNodeId; // admin.nodeInfo.id is 512 bit public key + bytes newNodeIp; + uint256 newNodePort; + uint256 lockAmount; + } + + //For GovernanceChange + struct BallotAddress { + uint256 id; + address newGovernanceAddress; + } + + //For EnvValChange + struct BallotVariable { + //Ballot ID + uint256 id; + bytes32 envVariableName; + uint256 envVariableType; + bytes envVariableValue; + } + + struct BallotExit { + // For exit + uint256 unlockAmount; + uint256 slashing; + } + + struct Vote { + uint256 voteId; + uint256 ballotId; + address voter; + uint256 decision; + uint256 power; + uint256 time; + } + + event BallotCreated(uint256 indexed ballotId, uint256 indexed ballotType, address indexed creator); + + event BallotStarted(uint256 indexed ballotId, uint256 indexed startTime, uint256 indexed endTime); + + event Voted(uint256 indexed voteid, uint256 indexed ballotId, address indexed voter, uint256 decision); + + event BallotFinalized(uint256 indexed ballotId, uint256 state); + + event BallotCanceled(uint256 indexed ballotId); + + event BallotUpdated(uint256 indexed ballotId, address indexed updatedBy); + + event SetPrevBallotStorage(address indexed previous); + + mapping(uint => BallotBasic) internal ballotBasicMap; + mapping(uint => BallotMember) internal ballotMemberMap; + mapping(uint => BallotAddress) internal ballotAddressMap; + mapping(uint => BallotVariable) internal ballotVariableMap; + + mapping(uint => Vote) internal voteMap; + mapping(uint => mapping(address => bool)) internal hasVotedMap; + + address internal previousBallotStorage; + + uint256 internal ballotCount; + + // For exit + mapping(uint => BallotExit) internal ballotExitMap; + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + function initialize(address _registry) external initializer { + __Ownable_init(); + setRegistry(_registry); + } + + modifier onlyValidTime(uint256 _startTime, uint256 _endTime) { + require(_startTime > 0 && _endTime > 0, "start or end is 0"); + require(_endTime > _startTime, "start >= end"); // && _startTime > getTime() + //uint256 diffTime = _endTime.sub(_startTime); + // require(diffTime > minBallotDuration()); + // require(diffTime <= maxBallotDuration()); + _; + } + + modifier onlyValidDuration(uint256 _duration) { + require(getMinVotingDuration() <= _duration, "Under min value of duration"); + require(_duration <= getMaxVotingDuration(), "Over max value of duration"); + _; + } + + modifier onlyGovOrCreator(uint256 _ballotId) { + require((getGovAddress() == msg.sender) || (ballotBasicMap[_ballotId].creator == msg.sender), "No Permission"); + _; + } + + modifier notDisabled() { + require(address(this) == getBallotStorageAddress(), "Is Disabled"); + _; + } + + function getMinVotingDuration() public view returns (uint256) { + return IEnvStorage(getEnvStorageAddress()).getBallotDurationMin(); + } + + function getMaxVotingDuration() public view returns (uint256) { + return IEnvStorage(getEnvStorageAddress()).getBallotDurationMax(); + } + + function getTime() public view returns (uint256) { + return block.timestamp; + } + + function getPreviousBallotStorage() public view returns (address) { + return previousBallotStorage; + } + + function isDisabled() public view returns (bool) { + return (address(this) != getBallotStorageAddress()); + } + + function getBallotCount() public view returns (uint256) { + return ballotCount; + } + + function getBallotBasic( + uint256 _id + ) + public + view + override + returns ( + uint256 startTime, + uint256 endTime, + uint256 ballotType, + address creator, + bytes memory memo, + uint256 totalVoters, + uint256 powerOfAccepts, + uint256 powerOfRejects, + uint256 state, + bool isFinalized, + uint256 duration + ) + { + BallotBasic memory tBallot = ballotBasicMap[_id]; + startTime = tBallot.startTime; + endTime = tBallot.endTime; + ballotType = tBallot.ballotType; + creator = tBallot.creator; + memo = tBallot.memo; + totalVoters = tBallot.totalVoters; + powerOfAccepts = tBallot.powerOfAccepts; + powerOfRejects = tBallot.powerOfRejects; + state = tBallot.state; + isFinalized = tBallot.isFinalized; + duration = tBallot.duration; + } + + function getBallotMember( + uint256 _id + ) + public + view + override + returns ( + address oldStakerAddress, + address newStakerAddress, + address newVoterAddress, + address newRewardAddress, + bytes memory newNodeName, // name + bytes memory newNodeId, // admin.nodeInfo.id is 512 bit public key + bytes memory newNodeIp, + uint256 newNodePort, + uint256 lockAmount + ) + { + BallotMember storage tBallot = ballotMemberMap[_id]; + oldStakerAddress = tBallot.oldStakerAddress; + newStakerAddress = tBallot.newStakerAddress; + newVoterAddress = tBallot.newVoterAddress; + newRewardAddress = tBallot.newRewardAddress; + newNodeName = tBallot.newNodeName; + newNodeId = tBallot.newNodeId; + newNodeIp = tBallot.newNodeIp; + newNodePort = tBallot.newNodePort; + lockAmount = tBallot.lockAmount; + } + + function getBallotAddress(uint256 _id) public view override returns (address newGovernanceAddress) { + BallotAddress storage tBallot = ballotAddressMap[_id]; + newGovernanceAddress = tBallot.newGovernanceAddress; + } + + function getBallotVariable( + uint256 _id + ) public view override returns (bytes32 envVariableName, uint256 envVariableType, bytes memory envVariableValue) { + BallotVariable storage tBallot = ballotVariableMap[_id]; + envVariableName = tBallot.envVariableName; + envVariableType = tBallot.envVariableType; + envVariableValue = tBallot.envVariableValue; + } + + function setPreviousBallotStorage(address _address) public onlyOwner { + require(_address != address(0), "Invalid address"); + previousBallotStorage = _address; + emit SetPrevBallotStorage(_address); + } + + //For MemberAdding/MemberRemoval/MemberSwap + function createBallotForMember( + uint256 _id, + uint256 _ballotType, + uint256 _duration, + address _creator, + address _oldStakerAddress, + address _newStakerAddress, + address _newVoterAddress, + address _newRewardAddress, + bytes memory _newNodeName, // name + bytes memory _newNodeId, // admin.nodeInfo.id is 512 bit public key + bytes memory _newNodeIp, + uint _newNodePort + ) public override onlyGov notDisabled { + require( + _areMemberBallotParamValid( + _ballotType, + _oldStakerAddress, + _newStakerAddress, + _newVoterAddress, + _newRewardAddress, + _newNodeName, + _newNodeId, + _newNodeIp, + _newNodePort + ), + "Invalid Parameter" + ); + _createBallot(_id, _ballotType, _duration, _creator); + BallotMember memory newBallot; + newBallot.id = _id; + newBallot.oldStakerAddress = _oldStakerAddress; + newBallot.newStakerAddress = _newStakerAddress; + newBallot.newVoterAddress = _newVoterAddress; + newBallot.newRewardAddress = _newRewardAddress; + newBallot.newNodeName = _newNodeName; + newBallot.newNodeId = _newNodeId; + newBallot.newNodeIp = _newNodeIp; + newBallot.newNodePort = _newNodePort; + + ballotMemberMap[_id] = newBallot; + } + + function createBallotForExit(uint256 _id, uint256 _unlockAmount, uint256 _slashing) public override onlyGov notDisabled { + ballotExitMap[_id].unlockAmount = _unlockAmount; + ballotExitMap[_id].slashing = _slashing; + } + function getBallotForExit(uint256 _id) public view override returns (uint256 unlockAmount, uint256 slashing) { + unlockAmount = ballotExitMap[_id].unlockAmount; + slashing = ballotExitMap[_id].slashing; + } + + function createBallotForAddress( + uint256 _id, + uint256 _ballotType, + uint256 _duration, + address _creator, + address _newGovernanceAddress + ) public override onlyGov notDisabled returns (uint256) { + require(_ballotType == uint256(BallotTypes.GovernanceChange), "Invalid Ballot Type"); + require(_newGovernanceAddress != address(0), "Invalid Parameter"); + _createBallot(_id, _ballotType, _duration, _creator); + BallotAddress memory newBallot; + newBallot.id = _id; + newBallot.newGovernanceAddress = _newGovernanceAddress; + ballotAddressMap[_id] = newBallot; + return _id; + } + + function createBallotForVariable( + uint256 _id, + uint256 _ballotType, + uint256 _duration, + address _creator, + bytes32 _envVariableName, + uint256 _envVariableType, + bytes memory _envVariableValue + ) public override onlyGov notDisabled returns (uint256) { + require(_areVariableBallotParamValid(_ballotType, _envVariableName, _envVariableValue), "Invalid Parameter"); + _createBallot(_id, _ballotType, _duration, _creator); + BallotVariable memory newBallot; + newBallot.id = _id; + newBallot.envVariableName = _envVariableName; + newBallot.envVariableType = _envVariableType; + newBallot.envVariableValue = _envVariableValue; + ballotVariableMap[_id] = newBallot; + return _id; + } + + function createVote(uint256 _voteId, uint256 _ballotId, address _voter, uint256 _decision, uint256 _power) public override onlyGov notDisabled { + // Check decision type + require((_decision == uint256(DecisionTypes.Accept)) || (_decision == uint256(DecisionTypes.Reject)), "Invalid decision"); + // Check if ballot exists + require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); + // Check if vote exists + require(voteMap[_voteId].voteId != _voteId, "already existed voteId"); + // Check if voted + require(!hasVotedMap[_ballotId][_voter], "already voted"); + require(ballotBasicMap[_ballotId].state == uint256(BallotStates.InProgress), "Not InProgress State"); + + voteMap[_voteId] = Vote(_voteId, _ballotId, _voter, _decision, _power, getTime()); + _updateBallotForVote(_ballotId, _voter, _decision, _power); + + emit Voted(_voteId, _ballotId, _voter, _decision); + } + + function startBallot( + uint256 _ballotId, + uint256 _startTime, + uint256 _endTime + ) public override onlyGov notDisabled onlyValidTime(_startTime, _endTime) { + require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); + require(ballotBasicMap[_ballotId].isFinalized == false, "already finalized"); + require(ballotBasicMap[_ballotId].state == uint256(BallotStates.Ready), "Not Ready State"); + + BallotBasic storage _ballot = ballotBasicMap[_ballotId]; + _ballot.startTime = _startTime; + _ballot.endTime = _endTime; + _ballot.state = uint256(BallotStates.InProgress); + emit BallotStarted(_ballotId, _startTime, _endTime); + } + + function updateBallotMemo(uint256 _ballotId, bytes memory _memo) public override onlyGovOrCreator(_ballotId) notDisabled { + require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); + require(ballotBasicMap[_ballotId].isFinalized == false, "already finalized"); + BallotBasic storage _ballot = ballotBasicMap[_ballotId]; + _ballot.memo = _memo; + emit BallotUpdated(_ballotId, msg.sender); + } + + function updateBallotDuration( + uint256 _ballotId, + uint256 _duration + ) public override onlyGovOrCreator(_ballotId) notDisabled onlyValidDuration(_duration) { + require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); + require(ballotBasicMap[_ballotId].isFinalized == false, "already finalized"); + require(ballotBasicMap[_ballotId].state == uint256(BallotStates.Ready), "Not Ready State"); + + BallotBasic storage _ballot = ballotBasicMap[_ballotId]; + _ballot.duration = _duration; + emit BallotUpdated(_ballotId, msg.sender); + } + + function updateBallotMemberLockAmount(uint256 _ballotId, uint256 _lockAmount) public override onlyGov notDisabled { + require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); + require(ballotMemberMap[_ballotId].id == _ballotId, "not existed BallotMember"); + require(ballotBasicMap[_ballotId].isFinalized == false, "already finalized"); + require(ballotBasicMap[_ballotId].state == uint256(BallotStates.Ready), "Not Ready State"); + BallotMember storage _ballot = ballotMemberMap[_ballotId]; + _ballot.lockAmount = _lockAmount; + emit BallotUpdated(_ballotId, msg.sender); + } + + // cancel ballot info + function cancelBallot(uint256 _ballotId) public onlyGovOrCreator(_ballotId) notDisabled { + require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); + require(ballotBasicMap[_ballotId].isFinalized == false, "already finalized"); + + require(ballotBasicMap[_ballotId].state == uint256(BallotStates.Ready), "Not Ready State"); + BallotBasic storage _ballot = ballotBasicMap[_ballotId]; + _ballot.state = uint256(BallotStates.Canceled); + emit BallotCanceled(_ballotId); + } + + // finalize ballot info + function finalizeBallot(uint256 _ballotId, uint256 _ballotState) public override onlyGov notDisabled { + require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); + require(ballotBasicMap[_ballotId].isFinalized == false, "already finalized"); + require((_ballotState == uint256(BallotStates.Accepted)) || (_ballotState == uint256(BallotStates.Rejected)), "Invalid Ballot State"); + + BallotBasic storage _ballot = ballotBasicMap[_ballotId]; + _ballot.state = _ballotState; + _ballot.isFinalized = true; + emit BallotFinalized(_ballotId, _ballotState); + } + + function hasAlreadyVoted(uint56 _ballotId, address _voter) public view returns (bool) { + return hasVotedMap[_ballotId][_voter]; + } + + function getVote( + uint256 _voteId + ) public view returns (uint256 voteId, uint256 ballotId, address voter, uint256 decision, uint256 power, uint256 time) { + require(voteMap[_voteId].voteId == _voteId, "not existed voteId"); + Vote memory _vote = voteMap[_voteId]; + voteId = _vote.voteId; + ballotId = _vote.ballotId; + voter = _vote.voter; + decision = _vote.decision; + power = _vote.power; + time = _vote.time; + } + + function getBallotPeriod(uint256 _id) public view override returns (uint256 startTime, uint256 endTime, uint256 duration) { + BallotBasic memory tBallot = ballotBasicMap[_id]; + startTime = tBallot.startTime; + endTime = tBallot.endTime; + duration = tBallot.duration; + } + + function getBallotVotingInfo(uint256 _id) public view override returns (uint256 totalVoters, uint256 powerOfAccepts, uint256 powerOfRejects) { + BallotBasic memory tBallot = ballotBasicMap[_id]; + totalVoters = tBallot.totalVoters; + powerOfAccepts = tBallot.powerOfAccepts; + powerOfRejects = tBallot.powerOfRejects; + } + + function getBallotState(uint256 _id) public view override returns (uint256 ballotType, uint256 state, bool isFinalized) { + BallotBasic memory tBallot = ballotBasicMap[_id]; + ballotType = tBallot.ballotType; + state = tBallot.state; + isFinalized = tBallot.isFinalized; + } + + function _createBallot(uint256 _id, uint256 _ballotType, uint256 _duration, address _creator) internal onlyValidDuration(_duration) { + require(ballotBasicMap[_id].id != _id, "Already existed ballot"); + + BallotBasic memory newBallot; + newBallot.id = _id; + newBallot.ballotType = _ballotType; + newBallot.creator = _creator; + // newBallot.memo = _memo; + newBallot.state = uint256(BallotStates.Ready); + newBallot.isFinalized = false; + newBallot.duration = _duration; + ballotBasicMap[_id] = newBallot; + ballotCount = ballotCount + 1; + emit BallotCreated(_id, _ballotType, _creator); + } + + function _areMemberBallotParamValid( + uint256 _ballotType, + address _oldStakerAddress, + address _newStakerAddress, + address _newVoterAddress, + address _newRewardAddress, + bytes memory _newName, + bytes memory _newNodeId, // admin.nodeInfo.id is 512 bit public key + bytes memory _newNodeIp, + uint _newNodePort + ) internal pure returns (bool) { + require((_ballotType >= uint256(BallotTypes.MemberAdd)) && (_ballotType <= uint256(BallotTypes.MemberChange)), "Invalid Ballot Type"); + + if (_ballotType == uint256(BallotTypes.MemberRemoval)) { + require(_oldStakerAddress != address(0), "Invalid old staker address"); + require(_newStakerAddress == address(0), "Invalid new staker address"); + require(_newVoterAddress == address(0), "Invalid new voter address"); + require(_newRewardAddress == address(0), "Invalid new reward address"); + require(_newName.length == 0, "Invalid new node name"); + require(_newNodeId.length == 0, "Invalid new node id"); + require(_newNodeIp.length == 0, "Invalid new node IP"); + require(_newNodePort == 0, "Invalid new node Port"); + } else { + require(_newName.length > 0, "Invalid new node name"); + require(_newNodeId.length == 64, "Invalid new node id"); + require(_newNodeIp.length > 0, "Invalid new node IP"); + require(_newNodePort > 0, "Invalid new node Port"); + if (_ballotType == uint256(BallotTypes.MemberAdd)) { + require(_oldStakerAddress == address(0), "Invalid old staker address"); + require(_newStakerAddress != address(0), "Invalid new staker address"); + require(_newVoterAddress != address(0), "Invalid new voter address"); + require(_newRewardAddress != address(0), "Invalid new reward address"); + } else if (_ballotType == uint256(BallotTypes.MemberChange)) { + require(_oldStakerAddress != address(0), "Invalid old staker address"); + require(_newStakerAddress != address(0), "Invalid new staker address"); + require(_newVoterAddress != address(0), "Invalid new voter address"); + require(_newRewardAddress != address(0), "Invalid new reward address"); + } + } + + return true; + } + + function _areVariableBallotParamValid( + uint256 _ballotType, + bytes32 _envVariableName, + bytes memory _envVariableValue + ) internal pure returns (bool) { + require(_ballotType == uint256(BallotTypes.EnvValChange), "Invalid Ballot Type"); + require(_envVariableName > 0, "Invalid environment variable name"); + require(_envVariableValue.length > 0, "Invalid environment variable value"); + + return true; + } + + // update ballot + function _updateBallotForVote(uint256 _ballotId, address _voter, uint256 _decision, uint256 _power) internal { + // c1. actionType 범위 + require((_decision == uint256(DecisionTypes.Accept)) || (_decision == uint256(DecisionTypes.Reject)), "Invalid decision"); + // c2. ballotId 존재 하는지 확인 + require(ballotBasicMap[_ballotId].id == _ballotId, "not existed Ballot"); + // c3. 이미 vote 했는지 확인 + require(hasVotedMap[_ballotId][_voter] == false, "already voted"); + + //1.get ballotBasic + BallotBasic storage _ballot = ballotBasicMap[_ballotId]; + //2. 투표 여부 등록 + hasVotedMap[_ballotId][_voter] = true; + //3. update totalVoters + _ballot.totalVoters = _ballot.totalVoters + 1; + //4. Update power of accept/reject + if (_decision == uint256(DecisionTypes.Accept)) { + _ballot.powerOfAccepts = _ballot.powerOfAccepts + _power; + } else { + _ballot.powerOfRejects = _ballot.powerOfRejects + _power; + } + } + + function upgradeBallotStorage(address newImp) external onlyOwner { + if (newImp != address(0)) { + _authorizeUpgrade(newImp); + _upgradeToAndCallUUPS(newImp, new bytes(0), false); + } + } + + function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} } diff --git a/wemix/governance-contract/contracts/storage/EnvStorage.sol b/wemix/governance-contract/contracts/storage/EnvStorage.sol index 82a3f7ce6882..c6dd88efdf7a 100644 --- a/wemix/governance-contract/contracts/storage/EnvStorage.sol +++ b/wemix/governance-contract/contracts/storage/EnvStorage.sol @@ -5,9 +5,9 @@ import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "@openzeppelin/contracts/proxy/beacon/IBeacon.sol"; contract EnvStorage is ERC1967Proxy, IBeacon { - constructor(address _implementation) ERC1967Proxy(_implementation, "") {} + constructor(address _implementation) ERC1967Proxy(_implementation, "") {} - function implementation() external view override returns (address) { - return _implementation(); - } + function implementation() external view override returns (address) { + return _implementation(); + } } diff --git a/wemix/governance-contract/contracts/storage/EnvStorageImp.sol b/wemix/governance-contract/contracts/storage/EnvStorageImp.sol index 391e744e3fcb..e29644c92032 100644 --- a/wemix/governance-contract/contracts/storage/EnvStorageImp.sol +++ b/wemix/governance-contract/contracts/storage/EnvStorageImp.sol @@ -7,12 +7,7 @@ import "../abstract/AEnvStorage.sol"; import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import "../interface/IEnvStorage.sol"; -contract EnvStorageImp is - AEnvStorage, - EnvConstants, - UUPSUpgradeable, - IEnvStorage -{ +contract EnvStorageImp is AEnvStorage, EnvConstants, UUPSUpgradeable, IEnvStorage { event UpgradeImplementation(address indexed implementation); /// @custom:oz-upgrades-unsafe-allow constructor @@ -20,15 +15,8 @@ contract EnvStorageImp is _disableInitializers(); } - function initialize( - address _registry, - bytes32[] memory names, - uint256[] memory infos - ) public initializer { - require( - _registry != _getImplementation(), - "registry should not be same as implementation" - ); + function initialize(address _registry, bytes32[] memory names, uint256[] memory infos) public initializer { + require(_registry != _getImplementation(), "registry should not be same as implementation"); __Ownable_init(); setRegistry(_registry); @@ -73,9 +61,7 @@ contract EnvStorageImp is return getUint(MAX_IDLE_BLOCK_INTERVAL_NAME); } - function _authorizeUpgrade( - address newImplementation - ) internal override onlyGov {} + function _authorizeUpgrade(address newImplementation) internal override onlyGov {} function setBlocksPer(uint256 _value) public onlyGov { setUint(BLOCKS_PER_NAME, _value); @@ -109,15 +95,11 @@ contract EnvStorageImp is setBlocksPer(toUint(_value)); } - function setBallotDurationMinByBytes( - bytes memory _value - ) public override onlyGov { + function setBallotDurationMinByBytes(bytes memory _value) public override onlyGov { setBallotDurationMin(toUint(_value)); } - function setBallotDurationMaxByBytes( - bytes memory _value - ) public override onlyGov { + function setBallotDurationMaxByBytes(bytes memory _value) public override onlyGov { setBallotDurationMax(toUint(_value)); } @@ -133,32 +115,17 @@ contract EnvStorageImp is // setGasPrice(toUint(_value)); // } - function setMaxIdleBlockIntervalByBytes( - bytes memory _value - ) public override onlyGov { + function setMaxIdleBlockIntervalByBytes(bytes memory _value) public override onlyGov { setMaxIdleBlockInterval(toUint(_value)); } //=======NXTMeta=======/ - function getBallotDurationMinMax() - public - view - override - returns (uint256, uint256) - { - return ( - getUint(BALLOT_DURATION_MIN_NAME), - getUint(BALLOT_DURATION_MAX_NAME) - ); + function getBallotDurationMinMax() public view override returns (uint256, uint256) { + return (getUint(BALLOT_DURATION_MIN_NAME), getUint(BALLOT_DURATION_MAX_NAME)); } - function getStakingMinMax() - public - view - override - returns (uint256, uint256) - { + function getStakingMinMax() public view override returns (uint256, uint256) { return (getUint(STAKING_MIN_NAME), getUint(STAKING_MAX_NAME)); } @@ -178,12 +145,7 @@ contract EnvStorageImp is return getUint(MAX_BASE_FEE_NAME); } - function getBlockRewardDistributionMethod() - public - view - override - returns (uint256, uint256, uint256, uint256) - { + function getBlockRewardDistributionMethod() public view override returns (uint256, uint256, uint256, uint256) { return ( getUint(BLOCK_REWARD_DISTRIBUTION_BLOCK_PRODUCER_NAME), getUint(BLOCK_REWARD_DISTRIBUTION_STAKING_REWARD_NAME), @@ -192,17 +154,8 @@ contract EnvStorageImp is ); } - function getGasLimitAndBaseFee() - public - view - override - returns (uint256, uint256, uint256) - { - return ( - getUint(BLOCK_GASLIMIT_NAME), - getUint(BASE_FEE_MAX_CHANGE_RATE_NAME), - getUint(GAS_TARGET_PERCENTAGE_NAME) - ); + function getGasLimitAndBaseFee() public view override returns (uint256, uint256, uint256) { + return (getUint(BLOCK_GASLIMIT_NAME), getUint(BASE_FEE_MAX_CHANGE_RATE_NAME), getUint(GAS_TARGET_PERCENTAGE_NAME)); } // function getStakingRewardAddress() public override view returns(address){ @@ -217,23 +170,14 @@ contract EnvStorageImp is // return getAddress(MAINTENANCE_ADDRESS_NAME); // } - function setBallotDurationMinMax( - uint256 _min, - uint256 _max - ) public override onlyGov { - require( - _min <= _max, - "Minimum duration must be smaller and equal than maximum duration" - ); + function setBallotDurationMinMax(uint256 _min, uint256 _max) public override onlyGov { + require(_min <= _max, "Minimum duration must be smaller and equal than maximum duration"); setUint(BALLOT_DURATION_MIN_NAME, _min); setUint(BALLOT_DURATION_MAX_NAME, _max); } function setStakingMinMax(uint256 _min, uint256 _max) public onlyGov { - require( - _min <= _max, - "Minimum staking must be smaller and equal than maximum staking" - ); + require(_min <= _max, "Minimum staking must be smaller and equal than maximum staking"); setUint(STAKING_MIN_NAME, _min); setUint(STAKING_MAX_NAME, _max); } @@ -260,11 +204,7 @@ contract EnvStorageImp is uint256 _ecofund, uint256 _maintenance ) public onlyGov { - require( - (_block_producer + _staking_reward + _ecofund + _maintenance) == - DENOMINATOR, - "Wrong reward distrubtion ratio" - ); + require((_block_producer + _staking_reward + _ecofund + _maintenance) == DENOMINATOR, "Wrong reward distrubtion ratio"); setUint(BLOCK_REWARD_DISTRIBUTION_BLOCK_PRODUCER_NAME, _block_producer); setUint(BLOCK_REWARD_DISTRIBUTION_STAKING_REWARD_NAME, _staking_reward); setUint(BLOCK_REWARD_DISTRIBUTION_ECOSYSTEM_NAME, _ecofund); @@ -283,35 +223,25 @@ contract EnvStorageImp is setUint(MAX_BASE_FEE_NAME, _maxBaseFee); } - function setBallotDurationMinMaxByBytes( - bytes memory _value - ) public override onlyGov { + function setBallotDurationMinMaxByBytes(bytes memory _value) public override onlyGov { (uint256 _min, uint256 _max) = to2Uint(_value); setBallotDurationMinMax(_min, _max); } - function setStakingMinMaxByBytes( - bytes memory _value - ) public override onlyGov { + function setStakingMinMaxByBytes(bytes memory _value) public override onlyGov { (uint256 _min, uint256 _max) = to2Uint(_value); setStakingMinMax(_min, _max); } - function setBlockCreationTimeByBytes( - bytes memory _value - ) public override onlyGov { + function setBlockCreationTimeByBytes(bytes memory _value) public override onlyGov { setBlockCreationTime(toUint(_value)); } - function setBlockRewardAmountByBytes( - bytes memory _value - ) public override onlyGov { + function setBlockRewardAmountByBytes(bytes memory _value) public override onlyGov { setBlockRewardAmount(toUint(_value)); } - function setMaxPriorityFeePerGasByBytes( - bytes memory _value - ) public override onlyGov { + function setMaxPriorityFeePerGasByBytes(bytes memory _value) public override onlyGov { setMaxPriorityFeePerGas(toUint(_value)); } @@ -319,59 +249,24 @@ contract EnvStorageImp is setMaxBaseFee(toUint(_value)); } - function setBlockRewardDistributionMethodByBytes( - bytes memory _value - ) public override onlyGov { - ( - uint256 _block_producer, - uint256 _staking_reward, - uint256 _ecosystem, - uint256 _maintenance - ) = to4Uint(_value); - setBlockRewardDistributionMethod( - _block_producer, - _staking_reward, - _ecosystem, - _maintenance - ); + function setBlockRewardDistributionMethodByBytes(bytes memory _value) public override onlyGov { + (uint256 _block_producer, uint256 _staking_reward, uint256 _ecosystem, uint256 _maintenance) = to4Uint(_value); + setBlockRewardDistributionMethod(_block_producer, _staking_reward, _ecosystem, _maintenance); } - function setGasLimitAndBaseFeeByBytes( - bytes memory _value - ) public override onlyGov { - ( - uint256 _block_GasLimit, - uint256 _baseFeeMaxChangeRate, - uint256 _gasTargetPercentage, - uint256 _maxBaseFee - ) = to4Uint(_value); - setGasLimitAndBaseFee( - _block_GasLimit, - _baseFeeMaxChangeRate, - _gasTargetPercentage, - _maxBaseFee - ); + function setGasLimitAndBaseFeeByBytes(bytes memory _value) public override onlyGov { + (uint256 _block_GasLimit, uint256 _baseFeeMaxChangeRate, uint256 _gasTargetPercentage, uint256 _maxBaseFee) = to4Uint(_value); + setGasLimitAndBaseFee(_block_GasLimit, _baseFeeMaxChangeRate, _gasTargetPercentage, _maxBaseFee); } - function checkVariableCondition( - bytes32 envKey, - bytes memory envVal - ) external pure override returns (bool) { + function checkVariableCondition(bytes32 envKey, bytes memory envVal) external pure override returns (bool) { if (envKey == BLOCK_REWARD_DISTRIBUTION_METHOD_NAME) { - ( - uint256 _block_producer, - uint256 _staking_reward, - uint256 _ecofund, - uint256 _maintenance - ) = abi.decode(envVal, (uint256, uint256, uint256, uint256)); - if ( - (_block_producer + _staking_reward + _ecofund + _maintenance) != - DENOMINATOR - ) return false; - } else if ( - envKey == STAKING_MIN_MAX_NAME || - envKey == BALLOT_DURATION_MIN_MAX_NAME - ) { + (uint256 _block_producer, uint256 _staking_reward, uint256 _ecofund, uint256 _maintenance) = abi.decode( + envVal, + (uint256, uint256, uint256, uint256) + ); + if ((_block_producer + _staking_reward + _ecofund + _maintenance) != DENOMINATOR) return false; + } else if (envKey == STAKING_MIN_MAX_NAME || envKey == BALLOT_DURATION_MIN_MAX_NAME) { (uint256 min, uint256 max) = abi.decode(envVal, (uint256, uint256)); if (min > max) return false; } else if (envKey == BLOCK_CREATION_TIME_NAME) { @@ -381,10 +276,7 @@ contract EnvStorageImp is return true; } - function setVariable( - bytes32 envKey, - bytes memory envVal - ) external override { + function setVariable(bytes32 envKey, bytes memory envVal) external override { if (envKey == BLOCKS_PER_NAME) { setBlocksPerByBytes(envVal); } else if (envKey == BALLOT_DURATION_MIN_MAX_NAME) { @@ -412,9 +304,7 @@ contract EnvStorageImp is } } - function toBytes32( - bytes memory _input - ) internal pure returns (bytes32 _output) { + function toBytes32(bytes memory _input) internal pure returns (bytes32 _output) { assembly { _output := mload(add(_input, 32)) } @@ -426,30 +316,20 @@ contract EnvStorageImp is } } - function toUint( - bytes memory _input - ) internal pure returns (uint256 _output) { + function toUint(bytes memory _input) internal pure returns (uint256 _output) { assembly { _output := mload(add(_input, 32)) } } - function to2Uint( - bytes memory _input - ) internal pure returns (uint256 _output0, uint256 _output1) { + function to2Uint(bytes memory _input) internal pure returns (uint256 _output0, uint256 _output1) { assembly { _output0 := mload(add(_input, 32)) _output1 := mload(add(_input, 64)) } } - function to3Uint( - bytes memory _input - ) - internal - pure - returns (uint256 _output0, uint256 _output1, uint256 _output2) - { + function to3Uint(bytes memory _input) internal pure returns (uint256 _output0, uint256 _output1, uint256 _output2) { assembly { _output0 := mload(add(_input, 32)) _output1 := mload(add(_input, 64)) @@ -457,18 +337,7 @@ contract EnvStorageImp is } } - function to4Uint( - bytes memory _input - ) - internal - pure - returns ( - uint256 _output0, - uint256 _output1, - uint256 _output2, - uint256 _output3 - ) - { + function to4Uint(bytes memory _input) internal pure returns (uint256 _output0, uint256 _output1, uint256 _output2, uint256 _output3) { assembly { _output0 := mload(add(_input, 32)) _output1 := mload(add(_input, 64)) @@ -477,9 +346,7 @@ contract EnvStorageImp is } } - function toAddress( - bytes memory _input - ) internal pure returns (address _output) { + function toAddress(bytes memory _input) internal pure returns (address _output) { _output = abi.decode(_input, (address)); // assembly { // _output := mload(add(_input, 20)) diff --git a/wemix/governance-contract/contracts/storage/EternalStorage.sol b/wemix/governance-contract/contracts/storage/EternalStorage.sol index d92448656902..b55908036a6a 100644 --- a/wemix/governance-contract/contracts/storage/EternalStorage.sol +++ b/wemix/governance-contract/contracts/storage/EternalStorage.sol @@ -7,141 +7,141 @@ pragma solidity ^0.8.0; * are stored in a set of mappings indexed by hash names. */ contract EternalStorage { - struct Storage { - mapping(bytes32 => bool) _bool; - mapping(bytes32 => int256) _int; - mapping(bytes32 => uint256) _uint; - mapping(bytes32 => string) _string; - mapping(bytes32 => address) _address; - mapping(bytes32 => bytes) _bytes; - mapping(bytes32 => bytes32) _bytes32; - } - - Storage internal s; - - /** - * @dev Get the value stored of a boolean variable by the hash name - * @param h The keccak256 hash of the variable name - */ - function getBoolean(bytes32 h) public view returns (bool) { - return s._bool[h]; - } - - /** - * @dev Get the value stored of a int variable by the hash name - * @param h The keccak256 hash of the variable name - */ - function getInt(bytes32 h) public view returns (int) { - return s._int[h]; - } - - /** - * @dev Get the value stored of a uint variable by the hash name - * @param h The keccak256 hash of the variable name - */ - function getUint(bytes32 h) public view returns (uint256) { - return s._uint[h]; - } - - /** - * @dev Get the value stored of a address variable by the hash name - * @param h The keccak256 hash of the variable name - */ - function getAddress(bytes32 h) public view returns (address) { - return s._address[h]; - } - - /** - * @dev Get the value stored of a string variable by the hash name - * @param h The keccak256 hash of the variable name - */ - function getString(bytes32 h) public view returns (string memory) { - return s._string[h]; - } - - /** - * @dev Get the value stored of a bytes variable by the hash name - * @param h The keccak256 hash of the variable name - */ - function getBytes(bytes32 h) public view returns (bytes memory) { - return s._bytes[h]; - } - - /** - * @dev Get the value stored of a bytes variable by the hash name - * @param h The keccak256 hash of the variable name - */ - function getBytes32(bytes32 h) public view returns (bytes32) { - return s._bytes32[h]; - } - - /** - * @dev Allows the owner to set a value for a boolean variable - * @param h The keccak256 hash of the variable name - * @param v The value to be stored - */ - function _setBoolean(bytes32 h, bool v) internal { - s._bool[h] = v; - } - - /** - * @dev Allows the owner to set a value for a int variable - * @param h The keccak256 hash of the variable name - * @param v The value to be stored - */ - function _setInt(bytes32 h, int256 v) internal { - s._int[h] = v; - } - - /** - * @dev Allows the owner to set a value for a boolean variable - * @param h The keccak256 hash of the variable name - * @param v The value to be stored - */ - function _setUint(bytes32 h, uint256 v) internal { - s._uint[h] = v; - } - - /** - * @dev Allows the owner to set a value for a address variable - * @param h The keccak256 hash of the variable name - * @param v The value to be stored - */ - function _setAddress(bytes32 h, address v) internal { - s._address[h] = v; - } - - /** - * @dev Allows the owner to set a value for a string variable - * @param h The keccak256 hash of the variable name - * @param v The value to be stored - */ - function _setString(bytes32 h, string memory v) internal { - s._string[h] = v; - } - - /** - * @dev Allows the owner to set a value for a bytes variable - * @param h The keccak256 hash of the variable name - * @param v The value to be stored - */ - function _setBytes(bytes32 h, bytes memory v) internal { - s._bytes[h] = v; - } - - /** - * @dev Allows the owner to set a value for a bytes32 variable - * @param h The keccak256 hash of the variable name - * @param v The value to be stored - */ - function _setBytes32(bytes32 h, bytes32 v) internal { - s._bytes32[h] = v; - } - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - */ - uint256[49] private __gap; + struct Storage { + mapping(bytes32 => bool) _bool; + mapping(bytes32 => int256) _int; + mapping(bytes32 => uint256) _uint; + mapping(bytes32 => string) _string; + mapping(bytes32 => address) _address; + mapping(bytes32 => bytes) _bytes; + mapping(bytes32 => bytes32) _bytes32; + } + + Storage internal s; + + /** + * @dev Get the value stored of a boolean variable by the hash name + * @param h The keccak256 hash of the variable name + */ + function getBoolean(bytes32 h) public view returns (bool) { + return s._bool[h]; + } + + /** + * @dev Get the value stored of a int variable by the hash name + * @param h The keccak256 hash of the variable name + */ + function getInt(bytes32 h) public view returns (int) { + return s._int[h]; + } + + /** + * @dev Get the value stored of a uint variable by the hash name + * @param h The keccak256 hash of the variable name + */ + function getUint(bytes32 h) public view returns (uint256) { + return s._uint[h]; + } + + /** + * @dev Get the value stored of a address variable by the hash name + * @param h The keccak256 hash of the variable name + */ + function getAddress(bytes32 h) public view returns (address) { + return s._address[h]; + } + + /** + * @dev Get the value stored of a string variable by the hash name + * @param h The keccak256 hash of the variable name + */ + function getString(bytes32 h) public view returns (string memory) { + return s._string[h]; + } + + /** + * @dev Get the value stored of a bytes variable by the hash name + * @param h The keccak256 hash of the variable name + */ + function getBytes(bytes32 h) public view returns (bytes memory) { + return s._bytes[h]; + } + + /** + * @dev Get the value stored of a bytes variable by the hash name + * @param h The keccak256 hash of the variable name + */ + function getBytes32(bytes32 h) public view returns (bytes32) { + return s._bytes32[h]; + } + + /** + * @dev Allows the owner to set a value for a boolean variable + * @param h The keccak256 hash of the variable name + * @param v The value to be stored + */ + function _setBoolean(bytes32 h, bool v) internal { + s._bool[h] = v; + } + + /** + * @dev Allows the owner to set a value for a int variable + * @param h The keccak256 hash of the variable name + * @param v The value to be stored + */ + function _setInt(bytes32 h, int256 v) internal { + s._int[h] = v; + } + + /** + * @dev Allows the owner to set a value for a boolean variable + * @param h The keccak256 hash of the variable name + * @param v The value to be stored + */ + function _setUint(bytes32 h, uint256 v) internal { + s._uint[h] = v; + } + + /** + * @dev Allows the owner to set a value for a address variable + * @param h The keccak256 hash of the variable name + * @param v The value to be stored + */ + function _setAddress(bytes32 h, address v) internal { + s._address[h] = v; + } + + /** + * @dev Allows the owner to set a value for a string variable + * @param h The keccak256 hash of the variable name + * @param v The value to be stored + */ + function _setString(bytes32 h, string memory v) internal { + s._string[h] = v; + } + + /** + * @dev Allows the owner to set a value for a bytes variable + * @param h The keccak256 hash of the variable name + * @param v The value to be stored + */ + function _setBytes(bytes32 h, bytes memory v) internal { + s._bytes[h] = v; + } + + /** + * @dev Allows the owner to set a value for a bytes32 variable + * @param h The keccak256 hash of the variable name + * @param v The value to be stored + */ + function _setBytes32(bytes32 h, bytes32 v) internal { + s._bytes32[h] = v; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[49] private __gap; }