From 4eb50fa014a5c5db7d0a6b453a421f2b46cb6a96 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Thu, 29 Feb 2024 17:12:51 +0800 Subject: [PATCH 01/66] add v2 voting --- contracts/solidity/GovernanceV2.sol | 109 ++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 contracts/solidity/GovernanceV2.sol diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol new file mode 100644 index 0000000000..3a13c12de4 --- /dev/null +++ b/contracts/solidity/GovernanceV2.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IGovernanceV2 { + event Vote(address voter, address to, uint amount); + event RevokeVote(address voter, address from, uint amount); + event WithdrawReward(address voter, uint reward); + + // vote draft with gas, only 1 target is allowed + function vote(address to) external payable; + + // withdraw ongoing vote + function revokeVote(address from) external; + + // withdraw past vote + function withdraw(address from) external; + + // get reward amount of addr + function getRewardAmount(address voter, address candidate) external view returns (uint); +} + +interface IGovReward { + function withdrawERC20(address to, address token, uint amount) external; + + function withdraw(address to, uint amount) external; +} + +contract GovernanceV2 is IGovernanceV2 { + // the min balance for voting + uint public constant MIN_VOTE_AMOUNT = 1 ether; + // GovReward contract + address public constant govReward = + 0x1212000000000000000000000000000000000003; + + mapping(address => mapping(uint => mapping(address => uint))) regularVotes; + mapping(address => mapping(address => uint[])) votedRounds; + + function getCurrentRound() public view returns (uint) { + return getRound(block.timestamp); + } + + function getRound(uint timestamp) public pure returns (uint) { + return timestamp / 1209600; + } + + function vote(address to) external payable { + require(msg.value >= MIN_VOTE_AMOUNT, "insufficient amount"); + uint currentRound = getCurrentRound(); + + uint voted = regularVotes[msg.sender][currentRound][to]; + // add this round to + if (voted == 0) { + votedRounds[msg.sender][to].push(currentRound); + } + regularVotes[msg.sender][currentRound][to] = voted + msg.value; + + emit Vote(msg.sender, to, msg.value); + } + + function revokeVote(address from) external { + uint currentRound = getCurrentRound(); + uint amount = regularVotes[msg.sender][currentRound][from]; + delete regularVotes[msg.sender][currentRound][from]; + safeTransferETH(msg.sender, amount); + } + + function withdraw(address from) external { + uint currentRound = getCurrentRound(); + uint totalAmount = 0; + uint[] memory votedIndex = votedRounds[msg.sender][from]; + uint indexLength = votedIndex.length; + for (uint i = 0; i < indexLength; i++) { + uint round = votedIndex[i]; + // only rounds before the current running one (the one before current voting) + if (round < currentRound - 1) { + uint roundAmount = regularVotes[msg.sender][round][from]; + delete regularVotes[msg.sender][round][from]; + delete votedRounds[msg.sender][from][i]; + totalAmount += roundAmount + getRoundReward(round, roundAmount); + } + } + safeTransferETH(msg.sender, totalAmount); + } + + function getRewardAmount(address voter, address candidate) external view returns (uint) { + uint currentRound = getCurrentRound(); + uint totalReward = 0; + uint[] memory votedIndex = votedRounds[voter][candidate]; + uint indexLength = votedIndex.length; + for (uint i = 0; i < indexLength; i++) { + uint round = votedIndex[i]; + // only rounds before the current running one (the one before current voting) + if (round < currentRound - 1) { + uint roundAmount = regularVotes[voter][round][candidate]; + totalReward += getRoundReward(round, roundAmount); + } + } + return totalReward; + } + + function getRoundReward(uint round, uint amount) public view returns (uint) { + return 0; + } + + function safeTransferETH(address to, uint value) internal { + (bool success, ) = to.call{value: value}(new bytes(0)); + require(success, "safeTransferETH: ETH transfer failed"); + } +} \ No newline at end of file From 830d8d4de8b004c7d4370d69c579d58a7a354d6f Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Thu, 29 Feb 2024 17:58:25 +0800 Subject: [PATCH 02/66] add candidate vote counter and some other details --- contracts/solidity/GovernanceV2.sol | 47 ++++++++++++++++++----------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 3a13c12de4..156f330c79 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -32,8 +32,12 @@ contract GovernanceV2 is IGovernanceV2 { address public constant govReward = 0x1212000000000000000000000000000000000003; - mapping(address => mapping(uint => mapping(address => uint))) regularVotes; + // voter=>round=>candidate=>amount + mapping(address => mapping(uint => mapping(address => uint))) voterTable; + // voter=>candidate=>rounds mapping(address => mapping(address => uint[])) votedRounds; + // candidate=>round=>amount + mapping(address => mapping(uint => uint)) receivedVotes; function getCurrentRound() public view returns (uint) { return getRound(block.timestamp); @@ -43,43 +47,50 @@ contract GovernanceV2 is IGovernanceV2 { return timestamp / 1209600; } - function vote(address to) external payable { + function vote(address candidateTo) external payable { require(msg.value >= MIN_VOTE_AMOUNT, "insufficient amount"); uint currentRound = getCurrentRound(); - uint voted = regularVotes[msg.sender][currentRound][to]; + uint voted = voterTable[msg.sender][currentRound][candidateTo]; // add this round to if (voted == 0) { - votedRounds[msg.sender][to].push(currentRound); + votedRounds[msg.sender][candidateTo].push(currentRound); } - regularVotes[msg.sender][currentRound][to] = voted + msg.value; + voterTable[msg.sender][currentRound][candidateTo] = voted + msg.value; + receivedVotes[candidateTo][currentRound] += msg.value; - emit Vote(msg.sender, to, msg.value); + emit Vote(msg.sender, candidateTo, msg.value); } - function revokeVote(address from) external { + function revokeVote(address candidateFrom) external { uint currentRound = getCurrentRound(); - uint amount = regularVotes[msg.sender][currentRound][from]; - delete regularVotes[msg.sender][currentRound][from]; + uint amount = voterTable[msg.sender][currentRound][candidateFrom]; + receivedVotes[candidateFrom][currentRound] -= amount; + delete voterTable[msg.sender][currentRound][candidateFrom]; safeTransferETH(msg.sender, amount); + + emit RevokeVote(msg.sender, candidateFrom, amount); } - function withdraw(address from) external { + function withdraw(address candidateFrom) external { uint currentRound = getCurrentRound(); uint totalAmount = 0; - uint[] memory votedIndex = votedRounds[msg.sender][from]; + uint totalReward = 0; + uint[] memory votedIndex = votedRounds[msg.sender][candidateFrom]; uint indexLength = votedIndex.length; for (uint i = 0; i < indexLength; i++) { uint round = votedIndex[i]; // only rounds before the current running one (the one before current voting) if (round < currentRound - 1) { - uint roundAmount = regularVotes[msg.sender][round][from]; - delete regularVotes[msg.sender][round][from]; - delete votedRounds[msg.sender][from][i]; - totalAmount += roundAmount + getRoundReward(round, roundAmount); + uint roundAmount = voterTable[msg.sender][round][candidateFrom]; + delete voterTable[msg.sender][round][candidateFrom]; + delete votedRounds[msg.sender][candidateFrom][i]; + totalAmount += roundAmount; + totalReward += getRoundReward(round, roundAmount); } } - safeTransferETH(msg.sender, totalAmount); + safeTransferETH(msg.sender, totalAmount + totalReward); + emit WithdrawReward(msg.sender, totalReward); } function getRewardAmount(address voter, address candidate) external view returns (uint) { @@ -91,14 +102,14 @@ contract GovernanceV2 is IGovernanceV2 { uint round = votedIndex[i]; // only rounds before the current running one (the one before current voting) if (round < currentRound - 1) { - uint roundAmount = regularVotes[voter][round][candidate]; + uint roundAmount = voterTable[voter][round][candidate]; totalReward += getRoundReward(round, roundAmount); } } return totalReward; } - function getRoundReward(uint round, uint amount) public view returns (uint) { + function getRoundReward(uint round, uint share) public view returns (uint) { return 0; } From a66057c46fdd843c4e02a27982b4c97435646da7 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Fri, 1 Mar 2024 16:27:45 +0800 Subject: [PATCH 03/66] make gas stable --- contracts/solidity/GovernanceV2.sol | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 156f330c79..450d2e9ff8 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -47,6 +47,14 @@ contract GovernanceV2 is IGovernanceV2 { return timestamp / 1209600; } + function getVotedValueByRound(address voter, uint round, address candidate) public view returns (uint) { + return voterTable[voter][round][candidate]; + } + + function getReceivedVotedByRound(address candidate, uint round) public view returns (uint) { + return receivedVotes[candidate][round]; + } + function vote(address candidateTo) external payable { require(msg.value >= MIN_VOTE_AMOUNT, "insufficient amount"); uint currentRound = getCurrentRound(); @@ -78,17 +86,29 @@ contract GovernanceV2 is IGovernanceV2 { uint totalReward = 0; uint[] memory votedIndex = votedRounds[msg.sender][candidateFrom]; uint indexLength = votedIndex.length; + bool reconstructed = false; for (uint i = 0; i < indexLength; i++) { uint round = votedIndex[i]; // only rounds before the current running one (the one before current voting) if (round < currentRound - 1) { uint roundAmount = voterTable[msg.sender][round][candidateFrom]; delete voterTable[msg.sender][round][candidateFrom]; - delete votedRounds[msg.sender][candidateFrom][i]; totalAmount += roundAmount; totalReward += getRoundReward(round, roundAmount); + } else if (round >= currentRound - 1) { + // reconstructed array, the new one always shorter than 2 + if (!reconstructed) { + // replace the old one + votedRounds[msg.sender][candidateFrom] = [round]; + } else { + votedRounds[msg.sender][candidateFrom].push(round); + } } } + // delete if all withdrawed + if (!reconstructed) { + delete votedRounds[msg.sender][candidateFrom]; + } safeTransferETH(msg.sender, totalAmount + totalReward); emit WithdrawReward(msg.sender, totalReward); } @@ -104,6 +124,8 @@ contract GovernanceV2 is IGovernanceV2 { if (round < currentRound - 1) { uint roundAmount = voterTable[voter][round][candidate]; totalReward += getRoundReward(round, roundAmount); + } else { + break; } } return totalReward; From e5d710afba761bdb0394f7c0b9712db4b2977aae Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Mon, 4 Mar 2024 10:18:55 +0800 Subject: [PATCH 04/66] use vote as round change trigger --- contracts/solidity/GovernanceV2.sol | 55 +++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 450d2e9ff8..1c110b56b7 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -16,7 +16,10 @@ interface IGovernanceV2 { function withdraw(address from) external; // get reward amount of addr - function getRewardAmount(address voter, address candidate) external view returns (uint); + function getRewardAmount( + address voter, + address candidate + ) external view returns (uint); } interface IGovReward { @@ -25,13 +28,17 @@ interface IGovReward { function withdraw(address to, uint amount) external; } -contract GovernanceV2 is IGovernanceV2 { +contract GovernanceV2 is IGovernanceV2 { // the min balance for voting uint public constant MIN_VOTE_AMOUNT = 1 ether; // GovReward contract address public constant govReward = 0x1212000000000000000000000000000000000003; + // the counter of round index + uint public roundCount; + // the timestamp of the last time when voting start + uint public lastRoundTime; // voter=>round=>candidate=>amount mapping(address => mapping(uint => mapping(address => uint))) voterTable; // voter=>candidate=>rounds @@ -40,24 +47,31 @@ contract GovernanceV2 is IGovernanceV2 { mapping(address => mapping(uint => uint)) receivedVotes; function getCurrentRound() public view returns (uint) { - return getRound(block.timestamp); - } - - function getRound(uint timestamp) public pure returns (uint) { - return timestamp / 1209600; + if (block.timestamp > lastRoundTime + 1209600) { + return roundCount + 1; + } else { + return roundCount; + } } - function getVotedValueByRound(address voter, uint round, address candidate) public view returns (uint) { + function getVotedValueByRound( + address voter, + uint round, + address candidate + ) public view returns (uint) { return voterTable[voter][round][candidate]; } - function getReceivedVotedByRound(address candidate, uint round) public view returns (uint) { + function getReceivedVotedByRound( + address candidate, + uint round + ) public view returns (uint) { return receivedVotes[candidate][round]; } function vote(address candidateTo) external payable { require(msg.value >= MIN_VOTE_AMOUNT, "insufficient amount"); - uint currentRound = getCurrentRound(); + uint currentRound = _getAndUpdateRoundCount(); uint voted = voterTable[msg.sender][currentRound][candidateTo]; // add this round to @@ -75,7 +89,7 @@ contract GovernanceV2 is IGovernanceV2 { uint amount = voterTable[msg.sender][currentRound][candidateFrom]; receivedVotes[candidateFrom][currentRound] -= amount; delete voterTable[msg.sender][currentRound][candidateFrom]; - safeTransferETH(msg.sender, amount); + _safeTransferETH(msg.sender, amount); emit RevokeVote(msg.sender, candidateFrom, amount); } @@ -109,11 +123,14 @@ contract GovernanceV2 is IGovernanceV2 { if (!reconstructed) { delete votedRounds[msg.sender][candidateFrom]; } - safeTransferETH(msg.sender, totalAmount + totalReward); + _safeTransferETH(msg.sender, totalAmount + totalReward); emit WithdrawReward(msg.sender, totalReward); } - function getRewardAmount(address voter, address candidate) external view returns (uint) { + function getRewardAmount( + address voter, + address candidate + ) external view returns (uint) { uint currentRound = getCurrentRound(); uint totalReward = 0; uint[] memory votedIndex = votedRounds[voter][candidate]; @@ -135,8 +152,16 @@ contract GovernanceV2 is IGovernanceV2 { return 0; } - function safeTransferETH(address to, uint value) internal { + function _getAndUpdateRoundCount() internal returns (uint) { + if (block.timestamp > lastRoundTime + 1209600) { + roundCount += 1; + lastRoundTime = block.timestamp; + } + return roundCount; + } + + function _safeTransferETH(address to, uint value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, "safeTransferETH: ETH transfer failed"); } -} \ No newline at end of file +} From 3a1edba09d7548c910c5214381a988d6ce784966 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 5 Mar 2024 15:00:48 +0800 Subject: [PATCH 05/66] fix bugs --- contracts/solidity/GovernanceV2.sol | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 1c110b56b7..c3d7f579bc 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -100,7 +100,7 @@ contract GovernanceV2 is IGovernanceV2 { uint totalReward = 0; uint[] memory votedIndex = votedRounds[msg.sender][candidateFrom]; uint indexLength = votedIndex.length; - bool reconstructed = false; + delete votedRounds[msg.sender][candidateFrom]; for (uint i = 0; i < indexLength; i++) { uint round = votedIndex[i]; // only rounds before the current running one (the one before current voting) @@ -111,18 +111,9 @@ contract GovernanceV2 is IGovernanceV2 { totalReward += getRoundReward(round, roundAmount); } else if (round >= currentRound - 1) { // reconstructed array, the new one always shorter than 2 - if (!reconstructed) { - // replace the old one - votedRounds[msg.sender][candidateFrom] = [round]; - } else { - votedRounds[msg.sender][candidateFrom].push(round); - } + votedRounds[msg.sender][candidateFrom].push(round); } } - // delete if all withdrawed - if (!reconstructed) { - delete votedRounds[msg.sender][candidateFrom]; - } _safeTransferETH(msg.sender, totalAmount + totalReward); emit WithdrawReward(msg.sender, totalReward); } From 9e3d28d3478ec2fc516e81d221bb0191aaebe62e Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 5 Mar 2024 15:02:22 +0800 Subject: [PATCH 06/66] add candidate list and sort method --- contracts/solidity/GovernanceV2.sol | 249 ++++++++++++++++++++++------ 1 file changed, 196 insertions(+), 53 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index c3d7f579bc..e7d2b0a0b0 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -2,11 +2,22 @@ pragma solidity ^0.8.0; interface IGovernanceV2 { + event Register(address candidate); + event Exit(address candidate); event Vote(address voter, address to, uint amount); event RevokeVote(address voter, address from, uint amount); event WithdrawReward(address voter, uint reward); - // vote draft with gas, only 1 target is allowed + // register to be a candidate with gas + function registerCandidate() external payable; + + // exit candidates and wait for withdraw + function exitCandidate() external; + + // withdraw register fee after 1 epoch + function claimRegisterFee() external; + + // vote with gas, only 1 target is allowed function vote(address to) external payable; // withdraw ongoing vote @@ -31,87 +42,158 @@ interface IGovReward { contract GovernanceV2 is IGovernanceV2 { // the min balance for voting uint public constant MIN_VOTE_AMOUNT = 1 ether; + // register fee + uint public constant REGISTER_FEE = 1000 ether; + // minimum duration of an epoch + uint public constant EPOCH_DURATION = 1209600; // GovReward contract address public constant govReward = 0x1212000000000000000000000000000000000003; - // the counter of round index - uint public roundCount; + // the counter of epoch index + uint public epochCount; // the timestamp of the last time when voting start - uint public lastRoundTime; - // voter=>round=>candidate=>amount + uint public lastEpochTime; + // candidate list + address[] public candidateList; + // the timestamp when register happen + mapping(address => uint) public registerTime; + // the timestamp when exit happen + mapping(address => uint) public exitTime; + // the left register fee to exit + mapping(address => uint) public feeBalance; + // epoch=>uint + mapping(uint => uint) public epochReward; + // voter=>epoch=>candidate=>amount mapping(address => mapping(uint => mapping(address => uint))) voterTable; - // voter=>candidate=>rounds - mapping(address => mapping(address => uint[])) votedRounds; - // candidate=>round=>amount + // voter=>candidate=>epochs + mapping(address => mapping(address => uint[])) votedEpochs; + // candidate=>epoch=>amount mapping(address => mapping(uint => uint)) receivedVotes; - function getCurrentRound() public view returns (uint) { - if (block.timestamp > lastRoundTime + 1209600) { - return roundCount + 1; + function getCurrentEpoch() public view returns (uint) { + if (block.timestamp > lastEpochTime + EPOCH_DURATION) { + return epochCount + 1; } else { - return roundCount; + return epochCount; } } - function getVotedValueByRound( + function getVotedValueByEpoch( address voter, - uint round, + uint epoch, address candidate ) public view returns (uint) { - return voterTable[voter][round][candidate]; + return voterTable[voter][epoch][candidate]; } - function getReceivedVotedByRound( + function getReceivedVotedByEpoch( address candidate, - uint round + uint epoch ) public view returns (uint) { - return receivedVotes[candidate][round]; + return receivedVotes[candidate][epoch]; + } + + function registerCandidate() external payable { + require(msg.value == REGISTER_FEE, "insufficient amount"); + address[] memory list = candidateList; + uint length = candidateList.length; + // check duplication + for (uint i = 0; i < length; i++) { + if (list[i] == msg.sender) { + revert("candidate exists"); + } + } + // delete exit record + delete exitTime[msg.sender]; + // add to candidates + candidateList.push(msg.sender); + // record register time and balance + registerTime[msg.sender] = block.timestamp; + feeBalance[msg.sender] = msg.value; + emit Register(msg.sender); + } + + function exitCandidate() external { + require(registerTime[msg.sender] > 0, "candidate not exists"); + // delete register time, cannot be voted + delete registerTime[msg.sender]; + // record exit time, but candidate list not removed, balance still locked + exitTime[msg.sender] = block.timestamp; + emit Exit(msg.sender); + } + + function claimRegisterFee() external { + // require 2 epochs to exit candidate list, so that the last round of vote can work as expected + require( + block.timestamp > exitTime[msg.sender] + 2 * EPOCH_DURATION, + "claim not allowed" + ); + + // reconstruct candidate list + address[] memory list = candidateList; + uint length = candidateList.length; + delete candidateList; + for (uint i = 0; i < length; i++) { + if (list[i] != msg.sender) { + candidateList.push(list[i]); + } + } + + // send back balance + uint amount = feeBalance[msg.sender]; + delete feeBalance[msg.sender]; + _safeTransferETH(msg.sender, amount); } function vote(address candidateTo) external payable { require(msg.value >= MIN_VOTE_AMOUNT, "insufficient amount"); - uint currentRound = _getAndUpdateRoundCount(); + require(registerTime[candidateTo] > 0, "candidate not allowed"); + // the first person vote in new epoch will pay for update + uint currentEpoch = _getAndUpdateEpochCount(); - uint voted = voterTable[msg.sender][currentRound][candidateTo]; - // add this round to + uint voted = voterTable[msg.sender][currentEpoch][candidateTo]; + // add this epoch to personal record if never voted if (voted == 0) { - votedRounds[msg.sender][candidateTo].push(currentRound); + votedEpochs[msg.sender][candidateTo].push(currentEpoch); } - voterTable[msg.sender][currentRound][candidateTo] = voted + msg.value; - receivedVotes[candidateTo][currentRound] += msg.value; + voterTable[msg.sender][currentEpoch][candidateTo] = voted + msg.value; + receivedVotes[candidateTo][currentEpoch] += msg.value; emit Vote(msg.sender, candidateTo, msg.value); } function revokeVote(address candidateFrom) external { - uint currentRound = getCurrentRound(); - uint amount = voterTable[msg.sender][currentRound][candidateFrom]; - receivedVotes[candidateFrom][currentRound] -= amount; - delete voterTable[msg.sender][currentRound][candidateFrom]; + // revoke will not trigger epoch change + uint currentEpoch = getCurrentEpoch(); + uint amount = voterTable[msg.sender][currentEpoch][candidateFrom]; + receivedVotes[candidateFrom][currentEpoch] -= amount; + delete voterTable[msg.sender][currentEpoch][candidateFrom]; _safeTransferETH(msg.sender, amount); emit RevokeVote(msg.sender, candidateFrom, amount); } function withdraw(address candidateFrom) external { - uint currentRound = getCurrentRound(); + // withdraw will not trigger epoch change + uint currentEpoch = getCurrentEpoch(); uint totalAmount = 0; uint totalReward = 0; - uint[] memory votedIndex = votedRounds[msg.sender][candidateFrom]; + // loop all voted epochs + uint[] memory votedIndex = votedEpochs[msg.sender][candidateFrom]; uint indexLength = votedIndex.length; - delete votedRounds[msg.sender][candidateFrom]; + delete votedEpochs[msg.sender][candidateFrom]; for (uint i = 0; i < indexLength; i++) { - uint round = votedIndex[i]; - // only rounds before the current running one (the one before current voting) - if (round < currentRound - 1) { - uint roundAmount = voterTable[msg.sender][round][candidateFrom]; - delete voterTable[msg.sender][round][candidateFrom]; - totalAmount += roundAmount; - totalReward += getRoundReward(round, roundAmount); - } else if (round >= currentRound - 1) { + uint epoch = votedIndex[i]; + // only epochs before the current running one (the one before current voting) + if (epoch < currentEpoch - 1) { + uint epochAmount = voterTable[msg.sender][epoch][candidateFrom]; + delete voterTable[msg.sender][epoch][candidateFrom]; + totalAmount += epochAmount; + totalReward += getEpochReward(epoch, epochAmount); + } else if (epoch >= currentEpoch - 1) { // reconstructed array, the new one always shorter than 2 - votedRounds[msg.sender][candidateFrom].push(round); + votedEpochs[msg.sender][candidateFrom].push(epoch); } } _safeTransferETH(msg.sender, totalAmount + totalReward); @@ -122,16 +204,16 @@ contract GovernanceV2 is IGovernanceV2 { address voter, address candidate ) external view returns (uint) { - uint currentRound = getCurrentRound(); + uint currentEpoch = getCurrentEpoch(); uint totalReward = 0; - uint[] memory votedIndex = votedRounds[voter][candidate]; + uint[] memory votedIndex = votedEpochs[voter][candidate]; uint indexLength = votedIndex.length; for (uint i = 0; i < indexLength; i++) { - uint round = votedIndex[i]; - // only rounds before the current running one (the one before current voting) - if (round < currentRound - 1) { - uint roundAmount = voterTable[voter][round][candidate]; - totalReward += getRoundReward(round, roundAmount); + uint epoch = votedIndex[i]; + // only epochs before the current running one (the one before current voting) + if (epoch < currentEpoch - 1) { + uint epochAmount = voterTable[voter][epoch][candidate]; + totalReward += getEpochReward(epoch, epochAmount); } else { break; } @@ -139,20 +221,81 @@ contract GovernanceV2 is IGovernanceV2 { return totalReward; } - function getRoundReward(uint round, uint share) public view returns (uint) { + function getEpochReward(uint epoch, uint share) public view returns (uint) { return 0; } - function _getAndUpdateRoundCount() internal returns (uint) { - if (block.timestamp > lastRoundTime + 1209600) { - roundCount += 1; - lastRoundTime = block.timestamp; + function getCurrentConsensus() public view returns (address[7] memory) { + // build up a votes array + uint length = candidateList.length; + uint epoch = epochCount - 1; + uint[] memory votes; + for (uint i = 0; i < length; i++) { + _push(votes, receivedVotes[candidateList[i]][epoch]); + } + address[] memory candidates = candidateList; + + // sort based on votes + _quickSort(candidates, votes, 0, int(length - 1)); + + // return the first 7 candidates as consensus list + address[7] memory consensus; + for (uint i = 0; i < 7; i++) { + consensus[i] = candidates[i]; + } + return consensus; + } + + function _getAndUpdateEpochCount() internal returns (uint) { + if (block.timestamp > lastEpochTime + EPOCH_DURATION) { + epochCount += 1; + lastEpochTime = block.timestamp; } - return roundCount; + return epochCount; } function _safeTransferETH(address to, uint value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, "safeTransferETH: ETH transfer failed"); } + + // sort candidates from high votes to low + function _quickSort( + address[] memory candidates, + uint[] memory votes, + int left, + int right + ) internal pure { + int i = left; + int j = right; + if (i == j) return; + uint pivot = votes[uint(left + (right - left) / 2)]; + while (i <= j) { + while (votes[uint(i)] < pivot) i++; + while (pivot < votes[uint(j)]) j--; + if (i <= j) { + (votes[uint(i)], votes[uint(j)]) = ( + votes[uint(j)], + votes[uint(i)] + ); + (candidates[uint(i)], candidates[uint(j)]) = ( + candidates[uint(j)], + candidates[uint(i)] + ); + i++; + j--; + } + } + if (left < j) _quickSort(candidates, votes, left, j); + if (i < right) _quickSort(candidates, votes, i, right); + } + + // push an element to the end of a memory array, note the array can not be changed if another dynamic array is declared after this + function _push(uint[] memory _nums, uint _num) internal pure { + assembly { + mstore(add(_nums, mul(add(mload(_nums), 1), 0x20)), _num) + mstore(_nums, add(mload(_nums), 1)) + mstore(0x40, add(mload(0x40), 0x20)) + } + } } From 3c29ff390d45e3e76858e1dcd278657cfcaf1c7f Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 5 Mar 2024 15:28:38 +0800 Subject: [PATCH 07/66] add v2 GovReward --- contracts/solidity/GovRewardV2.sol | 52 +++++++++++++++++++++++++++++ contracts/solidity/GovernanceV2.sol | 22 ++++++++---- 2 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 contracts/solidity/GovRewardV2.sol diff --git a/contracts/solidity/GovRewardV2.sol b/contracts/solidity/GovRewardV2.sol new file mode 100644 index 0000000000..f6f9bba607 --- /dev/null +++ b/contracts/solidity/GovRewardV2.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +library TransferHelper { + function safeTransfer(address token, address to, uint256 value) internal { + // bytes4(keccak256(bytes('transfer(address,uint256)'))); + (bool success, bytes memory data) = token.call( + abi.encodeWithSelector(0xa9059cbb, to, value) + ); + require( + success && (data.length == 0 || abi.decode(data, (bool))), + "safeTransfer: transfer failed" + ); + } + + function safeTransferETH(address to, uint256 value) internal { + (bool success, ) = to.call{value: value}(new bytes(0)); + require(success, "safeTransferETH: ETH transfer failed"); + } +} + +interface IGovernance { + // get current consensus group + function getCurrentConsensus() external view returns (address[7] memory); +} + +interface IGovReward { + function getMiners() external view returns (address[7] memory); + + function withdraw() external; +} + +contract GovReward is IGovReward { + // governance contact + address public constant governance = + 0x1212000000000000000000000000000000000001; + + receive() external payable {} + + modifier onlyGov() { + require(msg.sender == governance, "Not governance"); + _; + } + + function getMiners() external view override returns (address[7] memory) { + return IGovernance(governance).getCurrentConsensus(); + } + + function withdraw() external onlyGov { + TransferHelper.safeTransferETH(governance, address(this).balance); + } +} diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index e7d2b0a0b0..a730460d7f 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -26,6 +26,9 @@ interface IGovernanceV2 { // withdraw past vote function withdraw(address from) external; + // get current consensus group + function getCurrentConsensus() external view returns (address[7] memory); + // get reward amount of addr function getRewardAmount( address voter, @@ -34,9 +37,7 @@ interface IGovernanceV2 { } interface IGovReward { - function withdrawERC20(address to, address token, uint amount) external; - - function withdraw(address to, uint amount) external; + function withdraw() external; } contract GovernanceV2 is IGovernanceV2 { @@ -70,6 +71,12 @@ contract GovernanceV2 is IGovernanceV2 { mapping(address => mapping(address => uint[])) votedEpochs; // candidate=>epoch=>amount mapping(address => mapping(uint => uint)) receivedVotes; + // epoch=>amount + mapping(uint => uint) public totalVotes; + + receive() external payable { + epochReward[epochCount] += msg.value; + } function getCurrentEpoch() public view returns (uint) { if (block.timestamp > lastEpochTime + EPOCH_DURATION) { @@ -87,7 +94,7 @@ contract GovernanceV2 is IGovernanceV2 { return voterTable[voter][epoch][candidate]; } - function getReceivedVotedByEpoch( + function getReceivedVotesByEpoch( address candidate, uint epoch ) public view returns (uint) { @@ -159,6 +166,7 @@ contract GovernanceV2 is IGovernanceV2 { } voterTable[msg.sender][currentEpoch][candidateTo] = voted + msg.value; receivedVotes[candidateTo][currentEpoch] += msg.value; + totalVotes[currentEpoch] += msg.value; emit Vote(msg.sender, candidateTo, msg.value); } @@ -168,6 +176,7 @@ contract GovernanceV2 is IGovernanceV2 { uint currentEpoch = getCurrentEpoch(); uint amount = voterTable[msg.sender][currentEpoch][candidateFrom]; receivedVotes[candidateFrom][currentEpoch] -= amount; + totalVotes[currentEpoch] -= amount; delete voterTable[msg.sender][currentEpoch][candidateFrom]; _safeTransferETH(msg.sender, amount); @@ -222,10 +231,10 @@ contract GovernanceV2 is IGovernanceV2 { } function getEpochReward(uint epoch, uint share) public view returns (uint) { - return 0; + return share * epochReward[epoch] / totalVotes[epoch]; } - function getCurrentConsensus() public view returns (address[7] memory) { + function getCurrentConsensus() external view returns (address[7] memory) { // build up a votes array uint length = candidateList.length; uint epoch = epochCount - 1; @@ -248,6 +257,7 @@ contract GovernanceV2 is IGovernanceV2 { function _getAndUpdateEpochCount() internal returns (uint) { if (block.timestamp > lastEpochTime + EPOCH_DURATION) { + IGovReward(govReward).withdraw(); epochCount += 1; lastEpochTime = block.timestamp; } From b7d40274119e8b3c83267c0903edb1645964e793 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 5 Mar 2024 18:21:16 +0800 Subject: [PATCH 08/66] bugfix --- contracts/solidity/GovernanceV2.sol | 99 +++++++++-------------------- 1 file changed, 29 insertions(+), 70 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index a730460d7f..5cec9dc5fa 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -25,15 +25,6 @@ interface IGovernanceV2 { // withdraw past vote function withdraw(address from) external; - - // get current consensus group - function getCurrentConsensus() external view returns (address[7] memory); - - // get reward amount of addr - function getRewardAmount( - address voter, - address candidate - ) external view returns (uint); } interface IGovReward { @@ -71,8 +62,6 @@ contract GovernanceV2 is IGovernanceV2 { mapping(address => mapping(address => uint[])) votedEpochs; // candidate=>epoch=>amount mapping(address => mapping(uint => uint)) receivedVotes; - // epoch=>amount - mapping(uint => uint) public totalVotes; receive() external payable { epochReward[epochCount] += msg.value; @@ -106,15 +95,17 @@ contract GovernanceV2 is IGovernanceV2 { address[] memory list = candidateList; uint length = candidateList.length; // check duplication + bool existed = false; for (uint i = 0; i < length; i++) { if (list[i] == msg.sender) { - revert("candidate exists"); + existed = true; + break; } } - // delete exit record - delete exitTime[msg.sender]; - // add to candidates - candidateList.push(msg.sender); + if (!existed) { + // add to candidates + candidateList.push(msg.sender); + } // record register time and balance registerTime[msg.sender] = block.timestamp; feeBalance[msg.sender] = msg.value; @@ -137,16 +128,6 @@ contract GovernanceV2 is IGovernanceV2 { "claim not allowed" ); - // reconstruct candidate list - address[] memory list = candidateList; - uint length = candidateList.length; - delete candidateList; - for (uint i = 0; i < length; i++) { - if (list[i] != msg.sender) { - candidateList.push(list[i]); - } - } - // send back balance uint amount = feeBalance[msg.sender]; delete feeBalance[msg.sender]; @@ -166,7 +147,6 @@ contract GovernanceV2 is IGovernanceV2 { } voterTable[msg.sender][currentEpoch][candidateTo] = voted + msg.value; receivedVotes[candidateTo][currentEpoch] += msg.value; - totalVotes[currentEpoch] += msg.value; emit Vote(msg.sender, candidateTo, msg.value); } @@ -176,7 +156,6 @@ contract GovernanceV2 is IGovernanceV2 { uint currentEpoch = getCurrentEpoch(); uint amount = voterTable[msg.sender][currentEpoch][candidateFrom]; receivedVotes[candidateFrom][currentEpoch] -= amount; - totalVotes[currentEpoch] -= amount; delete voterTable[msg.sender][currentEpoch][candidateFrom]; _safeTransferETH(msg.sender, amount); @@ -184,8 +163,8 @@ contract GovernanceV2 is IGovernanceV2 { } function withdraw(address candidateFrom) external { - // withdraw will not trigger epoch change - uint currentEpoch = getCurrentEpoch(); + // withdraw use epochCount, to lock until epoch change + uint currentEpoch = epochCount; uint totalAmount = 0; uint totalReward = 0; // loop all voted epochs @@ -199,7 +178,18 @@ contract GovernanceV2 is IGovernanceV2 { uint epochAmount = voterTable[msg.sender][epoch][candidateFrom]; delete voterTable[msg.sender][epoch][candidateFrom]; totalAmount += epochAmount; - totalReward += getEpochReward(epoch, epochAmount); + + // calculate reward + address[7] memory consensus = getConsensus(epoch); + uint totalEffectiveVotes = 0; + uint userEffectiveVotes = 0; + for (uint j = 0; j < 7; j++) { + totalEffectiveVotes += receivedVotes[consensus[j]][epoch]; + if (consensus[j] == candidateFrom) { + userEffectiveVotes = epochAmount; + } + } + totalReward += userEffectiveVotes * epochReward[epoch] / totalEffectiveVotes; } else if (epoch >= currentEpoch - 1) { // reconstructed array, the new one always shorter than 2 votedEpochs[msg.sender][candidateFrom].push(epoch); @@ -209,40 +199,18 @@ contract GovernanceV2 is IGovernanceV2 { emit WithdrawReward(msg.sender, totalReward); } - function getRewardAmount( - address voter, - address candidate - ) external view returns (uint) { - uint currentEpoch = getCurrentEpoch(); - uint totalReward = 0; - uint[] memory votedIndex = votedEpochs[voter][candidate]; - uint indexLength = votedIndex.length; - for (uint i = 0; i < indexLength; i++) { - uint epoch = votedIndex[i]; - // only epochs before the current running one (the one before current voting) - if (epoch < currentEpoch - 1) { - uint epochAmount = voterTable[voter][epoch][candidate]; - totalReward += getEpochReward(epoch, epochAmount); - } else { - break; - } - } - return totalReward; - } - - function getEpochReward(uint epoch, uint share) public view returns (uint) { - return share * epochReward[epoch] / totalVotes[epoch]; + function getCurrentConsensus() public view returns (address[7] memory) { + return getConsensus(epochCount - 1); } - function getCurrentConsensus() external view returns (address[7] memory) { + function getConsensus(uint epoch) public view returns (address[7] memory) { // build up a votes array + address[] memory candidates = candidateList; uint length = candidateList.length; - uint epoch = epochCount - 1; - uint[] memory votes; + uint[] memory votes = new uint[](length); for (uint i = 0; i < length; i++) { - _push(votes, receivedVotes[candidateList[i]][epoch]); + votes[i] = receivedVotes[candidateList[i]][epoch]; } - address[] memory candidates = candidateList; // sort based on votes _quickSort(candidates, votes, 0, int(length - 1)); @@ -281,8 +249,8 @@ contract GovernanceV2 is IGovernanceV2 { if (i == j) return; uint pivot = votes[uint(left + (right - left) / 2)]; while (i <= j) { - while (votes[uint(i)] < pivot) i++; - while (pivot < votes[uint(j)]) j--; + while (votes[uint(i)] > pivot) i++; + while (pivot > votes[uint(j)]) j--; if (i <= j) { (votes[uint(i)], votes[uint(j)]) = ( votes[uint(j)], @@ -299,13 +267,4 @@ contract GovernanceV2 is IGovernanceV2 { if (left < j) _quickSort(candidates, votes, left, j); if (i < right) _quickSort(candidates, votes, i, right); } - - // push an element to the end of a memory array, note the array can not be changed if another dynamic array is declared after this - function _push(uint[] memory _nums, uint _num) internal pure { - assembly { - mstore(add(_nums, mul(add(mload(_nums), 1), 0x20)), _num) - mstore(_nums, add(mload(_nums), 1)) - mstore(0x40, add(mload(0x40), 0x20)) - } - } } From 14b0c95290dbe5d5645cf1ef896ed716571a8081 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 5 Mar 2024 18:27:29 +0800 Subject: [PATCH 09/66] split epoch definition --- contracts/solidity/GovernanceV2.sol | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 5cec9dc5fa..fc8fb43857 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -67,7 +67,7 @@ contract GovernanceV2 is IGovernanceV2 { epochReward[epochCount] += msg.value; } - function getCurrentEpoch() public view returns (uint) { + function getNominalCurrentEpoch() public view returns (uint) { if (block.timestamp > lastEpochTime + EPOCH_DURATION) { return epochCount + 1; } else { @@ -75,6 +75,10 @@ contract GovernanceV2 is IGovernanceV2 { } } + function getRealCurrentEpoch() public view returns (uint) { + return epochCount; + } + function getVotedValueByEpoch( address voter, uint epoch, @@ -153,7 +157,7 @@ contract GovernanceV2 is IGovernanceV2 { function revokeVote(address candidateFrom) external { // revoke will not trigger epoch change - uint currentEpoch = getCurrentEpoch(); + uint currentEpoch = getNominalCurrentEpoch(); uint amount = voterTable[msg.sender][currentEpoch][candidateFrom]; receivedVotes[candidateFrom][currentEpoch] -= amount; delete voterTable[msg.sender][currentEpoch][candidateFrom]; @@ -164,7 +168,7 @@ contract GovernanceV2 is IGovernanceV2 { function withdraw(address candidateFrom) external { // withdraw use epochCount, to lock until epoch change - uint currentEpoch = epochCount; + uint currentEpoch = getRealCurrentEpoch(); uint totalAmount = 0; uint totalReward = 0; // loop all voted epochs From c2901a7e0b163cee84cc0841a273e8699ed8e720 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Wed, 6 Mar 2024 11:05:00 +0800 Subject: [PATCH 10/66] add share setting, limit vote choice --- contracts/solidity/GovernanceV2.sol | 129 ++++++++++++++++------------ 1 file changed, 74 insertions(+), 55 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index fc8fb43857..796f084b94 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -9,7 +9,7 @@ interface IGovernanceV2 { event WithdrawReward(address voter, uint reward); // register to be a candidate with gas - function registerCandidate() external payable; + function registerCandidate(uint shareRate) external payable; // exit candidates and wait for withdraw function exitCandidate() external; @@ -21,10 +21,10 @@ interface IGovernanceV2 { function vote(address to) external payable; // withdraw ongoing vote - function revokeVote(address from) external; + function revokeVote() external; // withdraw past vote - function withdraw(address from) external; + function withdraw() external; } interface IGovReward { @@ -42,29 +42,33 @@ contract GovernanceV2 is IGovernanceV2 { address public constant govReward = 0x1212000000000000000000000000000000000003; - // the counter of epoch index + // counter of epoch index uint public epochCount; - // the timestamp of the last time when voting start + // timestamp of the last time when voting starts uint public lastEpochTime; // candidate list address[] public candidateList; - // the timestamp when register happen - mapping(address => uint) public registerTime; - // the timestamp when exit happen - mapping(address => uint) public exitTime; + // settings about how much reward given to voter + mapping(address => uint) public shareRateOf; + // timestamp when register happens + mapping(address => uint) public registerTimeOf; + // the timestamp when exit happens + mapping(address => uint) public exitTimeOf; // the left register fee to exit - mapping(address => uint) public feeBalance; + mapping(address => uint) public candidateBalanceOf; // epoch=>uint - mapping(uint => uint) public epochReward; - // voter=>epoch=>candidate=>amount - mapping(address => mapping(uint => mapping(address => uint))) voterTable; - // voter=>candidate=>epochs - mapping(address => mapping(address => uint[])) votedEpochs; + mapping(uint => uint) public epochRewards; + // voter=>epoch=>candidate + mapping(address => mapping(uint => address)) votedTo; + // voter=>epoch=>amount + mapping(address => mapping(uint => uint)) votedAmount; + // voter=>epochs + mapping(address => uint[]) votedEpochs; // candidate=>epoch=>amount mapping(address => mapping(uint => uint)) receivedVotes; receive() external payable { - epochReward[epochCount] += msg.value; + epochRewards[epochCount] += msg.value; } function getNominalCurrentEpoch() public view returns (uint) { @@ -79,12 +83,20 @@ contract GovernanceV2 is IGovernanceV2 { return epochCount; } - function getVotedValueByEpoch( + function _getAndUpdateEpochCount() internal returns (uint) { + if (block.timestamp > lastEpochTime + EPOCH_DURATION) { + IGovReward(govReward).withdraw(); + epochCount += 1; + lastEpochTime = block.timestamp; + } + return epochCount; + } + + function getVotedByEpoch( address voter, - uint epoch, - address candidate - ) public view returns (uint) { - return voterTable[voter][epoch][candidate]; + uint epoch + ) public view returns (address, uint) { + return (votedTo[voter][epoch], votedAmount[voter][epoch]); } function getReceivedVotesByEpoch( @@ -94,8 +106,9 @@ contract GovernanceV2 is IGovernanceV2 { return receivedVotes[candidate][epoch]; } - function registerCandidate() external payable { + function registerCandidate(uint shareRate) external payable { require(msg.value == REGISTER_FEE, "insufficient amount"); + require(shareRate < 1000, "invalid rate"); address[] memory list = candidateList; uint length = candidateList.length; // check duplication @@ -110,93 +123,108 @@ contract GovernanceV2 is IGovernanceV2 { // add to candidates candidateList.push(msg.sender); } - // record register time and balance - registerTime[msg.sender] = block.timestamp; - feeBalance[msg.sender] = msg.value; + // record register time, share rate and balance + registerTimeOf[msg.sender] = block.timestamp; + shareRateOf[msg.sender] = shareRate; + candidateBalanceOf[msg.sender] = msg.value; emit Register(msg.sender); } function exitCandidate() external { - require(registerTime[msg.sender] > 0, "candidate not exists"); + require(registerTimeOf[msg.sender] > 0, "candidate not exists"); // delete register time, cannot be voted - delete registerTime[msg.sender]; + delete registerTimeOf[msg.sender]; // record exit time, but candidate list not removed, balance still locked - exitTime[msg.sender] = block.timestamp; + exitTimeOf[msg.sender] = block.timestamp; emit Exit(msg.sender); } function claimRegisterFee() external { // require 2 epochs to exit candidate list, so that the last round of vote can work as expected require( - block.timestamp > exitTime[msg.sender] + 2 * EPOCH_DURATION, + block.timestamp > exitTimeOf[msg.sender] + 2 * EPOCH_DURATION, "claim not allowed" ); // send back balance - uint amount = feeBalance[msg.sender]; - delete feeBalance[msg.sender]; + uint amount = candidateBalanceOf[msg.sender]; + delete candidateBalanceOf[msg.sender]; _safeTransferETH(msg.sender, amount); } function vote(address candidateTo) external payable { require(msg.value >= MIN_VOTE_AMOUNT, "insufficient amount"); - require(registerTime[candidateTo] > 0, "candidate not allowed"); + require(registerTimeOf[candidateTo] > 0, "candidate not allowed"); // the first person vote in new epoch will pay for update uint currentEpoch = _getAndUpdateEpochCount(); - uint voted = voterTable[msg.sender][currentEpoch][candidateTo]; + uint voted = votedAmount[msg.sender][currentEpoch]; // add this epoch to personal record if never voted if (voted == 0) { - votedEpochs[msg.sender][candidateTo].push(currentEpoch); + votedTo[msg.sender][currentEpoch] = candidateTo; + votedEpochs[msg.sender].push(currentEpoch); + } else { + require( + votedTo[msg.sender][currentEpoch] == candidateTo, + "only one choice is allowed" + ); } - voterTable[msg.sender][currentEpoch][candidateTo] = voted + msg.value; + votedAmount[msg.sender][currentEpoch] = voted + msg.value; receivedVotes[candidateTo][currentEpoch] += msg.value; emit Vote(msg.sender, candidateTo, msg.value); } - function revokeVote(address candidateFrom) external { + function revokeVote() external { // revoke will not trigger epoch change uint currentEpoch = getNominalCurrentEpoch(); - uint amount = voterTable[msg.sender][currentEpoch][candidateFrom]; + address candidateFrom = votedTo[msg.sender][currentEpoch]; + uint amount = votedAmount[msg.sender][currentEpoch]; receivedVotes[candidateFrom][currentEpoch] -= amount; - delete voterTable[msg.sender][currentEpoch][candidateFrom]; + delete votedTo[msg.sender][currentEpoch]; + delete votedAmount[msg.sender][currentEpoch]; _safeTransferETH(msg.sender, amount); emit RevokeVote(msg.sender, candidateFrom, amount); } - function withdraw(address candidateFrom) external { + function withdraw() external { // withdraw use epochCount, to lock until epoch change uint currentEpoch = getRealCurrentEpoch(); uint totalAmount = 0; uint totalReward = 0; // loop all voted epochs - uint[] memory votedIndex = votedEpochs[msg.sender][candidateFrom]; + uint[] memory votedIndex = votedEpochs[msg.sender]; uint indexLength = votedIndex.length; - delete votedEpochs[msg.sender][candidateFrom]; + delete votedEpochs[msg.sender]; for (uint i = 0; i < indexLength; i++) { uint epoch = votedIndex[i]; // only epochs before the current running one (the one before current voting) if (epoch < currentEpoch - 1) { - uint epochAmount = voterTable[msg.sender][epoch][candidateFrom]; - delete voterTable[msg.sender][epoch][candidateFrom]; + uint epochAmount = votedAmount[msg.sender][epoch]; + delete votedAmount[msg.sender][epoch]; totalAmount += epochAmount; // calculate reward + address candidate = votedTo[msg.sender][epoch]; address[7] memory consensus = getConsensus(epoch); uint totalEffectiveVotes = 0; uint userEffectiveVotes = 0; for (uint j = 0; j < 7; j++) { totalEffectiveVotes += receivedVotes[consensus[j]][epoch]; - if (consensus[j] == candidateFrom) { + if (consensus[j] == candidate) { userEffectiveVotes = epochAmount; } } - totalReward += userEffectiveVotes * epochReward[epoch] / totalEffectiveVotes; + totalReward += + (userEffectiveVotes * + epochRewards[epoch] * + shareRateOf[candidate]) / + totalEffectiveVotes / + 1000; } else if (epoch >= currentEpoch - 1) { // reconstructed array, the new one always shorter than 2 - votedEpochs[msg.sender][candidateFrom].push(epoch); + votedEpochs[msg.sender].push(epoch); } } _safeTransferETH(msg.sender, totalAmount + totalReward); @@ -227,15 +255,6 @@ contract GovernanceV2 is IGovernanceV2 { return consensus; } - function _getAndUpdateEpochCount() internal returns (uint) { - if (block.timestamp > lastEpochTime + EPOCH_DURATION) { - IGovReward(govReward).withdraw(); - epochCount += 1; - lastEpochTime = block.timestamp; - } - return epochCount; - } - function _safeTransferETH(address to, uint value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, "safeTransferETH: ETH transfer failed"); From f9e36ef4a7f7680366273086349d9713ce769627 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Wed, 6 Mar 2024 11:36:09 +0800 Subject: [PATCH 11/66] add candidate claim --- contracts/solidity/GovernanceV2.sol | 86 ++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 19 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 796f084b94..bcc79ae871 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -6,7 +6,8 @@ interface IGovernanceV2 { event Exit(address candidate); event Vote(address voter, address to, uint amount); event RevokeVote(address voter, address from, uint amount); - event WithdrawReward(address voter, uint reward); + event VoterWithdraw(address voter, uint votes, uint reward); + event CandidateClaim(address candidate, uint reward); // register to be a candidate with gas function registerCandidate(uint shareRate) external payable; @@ -20,11 +21,14 @@ interface IGovernanceV2 { // vote with gas, only 1 target is allowed function vote(address to) external payable; - // withdraw ongoing vote + // revoke ongoing vote function revokeVote() external; // withdraw past vote - function withdraw() external; + function voterWithdraw() external; + + // claim rewards for being a consensus member + function candidateClaim() external; } interface IGovReward { @@ -59,16 +63,18 @@ contract GovernanceV2 is IGovernanceV2 { // epoch=>uint mapping(uint => uint) public epochRewards; // voter=>epoch=>candidate - mapping(address => mapping(uint => address)) votedTo; + mapping(address => mapping(uint => address)) public votedTo; // voter=>epoch=>amount - mapping(address => mapping(uint => uint)) votedAmount; + mapping(address => mapping(uint => uint)) public votedAmount; // voter=>epochs - mapping(address => uint[]) votedEpochs; + mapping(address => uint[]) public unclaimedEpochsOf; // candidate=>epoch=>amount - mapping(address => mapping(uint => uint)) receivedVotes; + mapping(address => mapping(uint => uint)) public receivedVotes; + // candidate=>epoch + mapping(address => uint) public lastClaimedEpochOf; receive() external payable { - epochRewards[epochCount] += msg.value; + epochRewards[getRealCurrentEpoch()] += msg.value; } function getNominalCurrentEpoch() public view returns (uint) { @@ -127,6 +133,8 @@ contract GovernanceV2 is IGovernanceV2 { registerTimeOf[msg.sender] = block.timestamp; shareRateOf[msg.sender] = shareRate; candidateBalanceOf[msg.sender] = msg.value; + // set the start point for claim + lastClaimedEpochOf[msg.sender] = getRealCurrentEpoch(); emit Register(msg.sender); } @@ -162,7 +170,7 @@ contract GovernanceV2 is IGovernanceV2 { // add this epoch to personal record if never voted if (voted == 0) { votedTo[msg.sender][currentEpoch] = candidateTo; - votedEpochs[msg.sender].push(currentEpoch); + unclaimedEpochsOf[msg.sender].push(currentEpoch); } else { require( votedTo[msg.sender][currentEpoch] == candidateTo, @@ -188,15 +196,15 @@ contract GovernanceV2 is IGovernanceV2 { emit RevokeVote(msg.sender, candidateFrom, amount); } - function withdraw() external { - // withdraw use epochCount, to lock until epoch change + function voterWithdraw() external { + // use epochCount, to lock votes and rewards until epoch change uint currentEpoch = getRealCurrentEpoch(); uint totalAmount = 0; uint totalReward = 0; // loop all voted epochs - uint[] memory votedIndex = votedEpochs[msg.sender]; + uint[] memory votedIndex = unclaimedEpochsOf[msg.sender]; uint indexLength = votedIndex.length; - delete votedEpochs[msg.sender]; + delete unclaimedEpochsOf[msg.sender]; for (uint i = 0; i < indexLength; i++) { uint epoch = votedIndex[i]; // only epochs before the current running one (the one before current voting) @@ -209,30 +217,70 @@ contract GovernanceV2 is IGovernanceV2 { address candidate = votedTo[msg.sender][epoch]; address[7] memory consensus = getConsensus(epoch); uint totalEffectiveVotes = 0; - uint userEffectiveVotes = 0; + uint voterEffectiveVotes = 0; for (uint j = 0; j < 7; j++) { totalEffectiveVotes += receivedVotes[consensus[j]][epoch]; if (consensus[j] == candidate) { - userEffectiveVotes = epochAmount; + voterEffectiveVotes = epochAmount; } } totalReward += - (userEffectiveVotes * + (voterEffectiveVotes * epochRewards[epoch] * shareRateOf[candidate]) / totalEffectiveVotes / 1000; } else if (epoch >= currentEpoch - 1) { // reconstructed array, the new one always shorter than 2 - votedEpochs[msg.sender].push(epoch); + unclaimedEpochsOf[msg.sender].push(epoch); } } _safeTransferETH(msg.sender, totalAmount + totalReward); - emit WithdrawReward(msg.sender, totalReward); + emit VoterWithdraw(msg.sender, totalAmount, totalReward); + } + + function candidateClaim() external { + require( + registerTimeOf[msg.sender] > 0 || exitTimeOf[msg.sender] > 0, + "not a candidate" + ); + // use epochCount, to lock rewards until epoch change + uint currentEpoch = getRealCurrentEpoch(); + require(currentEpoch > 2, "claim not started"); + uint totalReward = 0; + // loop all unclaimed epochs + for ( + uint i = lastClaimedEpochOf[msg.sender] + 1; + i < currentEpoch - 1; + i++ + ) { + // only epochs before the current running one (the one before current voting) + uint receivedVote = receivedVotes[msg.sender][i]; + + // calculate reward + address[7] memory consensus = getConsensus(i); + uint totalEffectiveVotes = 0; + uint candidateEffectiveVotes = 0; + for (uint j = 0; j < 7; j++) { + totalEffectiveVotes += receivedVotes[consensus[j]][i]; + if (consensus[j] == msg.sender) { + candidateEffectiveVotes = receivedVote; + } + } + totalReward += + (candidateEffectiveVotes * + epochRewards[i] * + (1000 - shareRateOf[msg.sender])) / + totalEffectiveVotes / + 1000; + } + lastClaimedEpochOf[msg.sender] = currentEpoch - 2; + _safeTransferETH(msg.sender, totalReward); + emit CandidateClaim(msg.sender, totalReward); } function getCurrentConsensus() public view returns (address[7] memory) { - return getConsensus(epochCount - 1); + return getConsensus(getRealCurrentEpoch() - 1); } function getConsensus(uint epoch) public view returns (address[7] memory) { From 4b1bc9c8d88dcd197d116e7351e5fc1963d7cc44 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Wed, 6 Mar 2024 15:31:41 +0800 Subject: [PATCH 12/66] add cache for getting consensus --- contracts/solidity/GovernanceV2.sol | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index bcc79ae871..4a293386b6 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -72,6 +72,8 @@ contract GovernanceV2 is IGovernanceV2 { mapping(address => mapping(uint => uint)) public receivedVotes; // candidate=>epoch mapping(address => uint) public lastClaimedEpochOf; + // epoch=>consensus + mapping(uint => address[7]) private consensusCache; receive() external payable { epochRewards[getRealCurrentEpoch()] += msg.value; @@ -215,7 +217,7 @@ contract GovernanceV2 is IGovernanceV2 { // calculate reward address candidate = votedTo[msg.sender][epoch]; - address[7] memory consensus = getConsensus(epoch); + address[7] memory consensus = _tryGetAndCacheConsensus(epoch); uint totalEffectiveVotes = 0; uint voterEffectiveVotes = 0; for (uint j = 0; j < 7; j++) { @@ -258,7 +260,7 @@ contract GovernanceV2 is IGovernanceV2 { uint receivedVote = receivedVotes[msg.sender][i]; // calculate reward - address[7] memory consensus = getConsensus(i); + address[7] memory consensus = _tryGetAndCacheConsensus(i); uint totalEffectiveVotes = 0; uint candidateEffectiveVotes = 0; for (uint j = 0; j < 7; j++) { @@ -284,6 +286,23 @@ contract GovernanceV2 is IGovernanceV2 { } function getConsensus(uint epoch) public view returns (address[7] memory) { + address[7] memory cache = consensusCache[epoch]; + if (cache[0] == address(0)) { + return getConsensus(epoch); + } + return cache; + } + + function _tryGetAndCacheConsensus(uint epoch) internal returns (address[7] memory) { + address[7] memory cache = consensusCache[epoch]; + if (cache[0] == address(0)) { + cache = _getConsensus(epoch); + consensusCache[epoch] = cache; + } + return cache; + } + + function _getConsensus(uint epoch) internal view returns (address[7] memory) { // build up a votes array address[] memory candidates = candidateList; uint length = candidateList.length; From b50d17f0e0eb4e2886d09fe7df28f64dee859474 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Wed, 6 Mar 2024 16:26:35 +0800 Subject: [PATCH 13/66] update reward distribution, bugfix --- contracts/solidity/GovernanceV2.sol | 52 ++++++++++++++--------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 4a293386b6..754ef890fd 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -218,20 +218,21 @@ contract GovernanceV2 is IGovernanceV2 { // calculate reward address candidate = votedTo[msg.sender][epoch]; address[7] memory consensus = _tryGetAndCacheConsensus(epoch); - uint totalEffectiveVotes = 0; - uint voterEffectiveVotes = 0; + bool included = false; for (uint j = 0; j < 7; j++) { - totalEffectiveVotes += receivedVotes[consensus[j]][epoch]; if (consensus[j] == candidate) { - voterEffectiveVotes = epochAmount; + included = true; } } - totalReward += - (voterEffectiveVotes * - epochRewards[epoch] * - shareRateOf[candidate]) / - totalEffectiveVotes / - 1000; + if (included) { + totalReward += + (epochAmount * + epochRewards[epoch] * + shareRateOf[candidate]) / + receivedVotes[candidate][epoch] / + 7 / + 1000; + } } else if (epoch >= currentEpoch - 1) { // reconstructed array, the new one always shorter than 2 unclaimedEpochsOf[msg.sender].push(epoch); @@ -257,24 +258,19 @@ contract GovernanceV2 is IGovernanceV2 { i++ ) { // only epochs before the current running one (the one before current voting) - uint receivedVote = receivedVotes[msg.sender][i]; - - // calculate reward address[7] memory consensus = _tryGetAndCacheConsensus(i); - uint totalEffectiveVotes = 0; - uint candidateEffectiveVotes = 0; + bool included = false; for (uint j = 0; j < 7; j++) { - totalEffectiveVotes += receivedVotes[consensus[j]][i]; if (consensus[j] == msg.sender) { - candidateEffectiveVotes = receivedVote; + included = true; } } - totalReward += - (candidateEffectiveVotes * - epochRewards[i] * - (1000 - shareRateOf[msg.sender])) / - totalEffectiveVotes / - 1000; + if (included) { + totalReward += + (epochRewards[i] * (1000 - shareRateOf[msg.sender])) / + 7 / + 1000; + } } lastClaimedEpochOf[msg.sender] = currentEpoch - 2; _safeTransferETH(msg.sender, totalReward); @@ -288,12 +284,14 @@ contract GovernanceV2 is IGovernanceV2 { function getConsensus(uint epoch) public view returns (address[7] memory) { address[7] memory cache = consensusCache[epoch]; if (cache[0] == address(0)) { - return getConsensus(epoch); + return _getConsensus(epoch); } return cache; } - function _tryGetAndCacheConsensus(uint epoch) internal returns (address[7] memory) { + function _tryGetAndCacheConsensus( + uint epoch + ) internal returns (address[7] memory) { address[7] memory cache = consensusCache[epoch]; if (cache[0] == address(0)) { cache = _getConsensus(epoch); @@ -302,7 +300,9 @@ contract GovernanceV2 is IGovernanceV2 { return cache; } - function _getConsensus(uint epoch) internal view returns (address[7] memory) { + function _getConsensus( + uint epoch + ) internal view returns (address[7] memory) { // build up a votes array address[] memory candidates = candidateList; uint length = candidateList.length; From 282c41394444a5c08d4391ed422570c414073e12 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Wed, 6 Mar 2024 16:57:34 +0800 Subject: [PATCH 14/66] relate epoch i to reward i+1 --- contracts/solidity/GovernanceV2.sol | 31 +++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 754ef890fd..d08f3f3f74 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -75,8 +75,26 @@ contract GovernanceV2 is IGovernanceV2 { // epoch=>consensus mapping(uint => address[7]) private consensusCache; + constructor() { + address[7] memory initialConsensus = [ + address(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266), + address(0x70997970C51812dc3A010C7d01b50e0d17dc79C8), + address(0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC), + address(0x90F79bf6EB2c4f870365E785982E1f101E93b906), + address(0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65), + address(0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc), + address(0x976EA74026E726554dB657fA54763abd0C3a0aa9) + ]; + consensusCache[0] = initialConsensus; + } + receive() external payable { - epochRewards[getRealCurrentEpoch()] += msg.value; + uint epoch = getRealCurrentEpoch(); + if (epoch > 0) { + epochRewards[epoch] += msg.value; + } else { + epochRewards[epoch + 1] += msg.value; + } } function getNominalCurrentEpoch() public view returns (uint) { @@ -227,7 +245,7 @@ contract GovernanceV2 is IGovernanceV2 { if (included) { totalReward += (epochAmount * - epochRewards[epoch] * + epochRewards[epoch + 1] * shareRateOf[candidate]) / receivedVotes[candidate][epoch] / 7 / @@ -267,7 +285,7 @@ contract GovernanceV2 is IGovernanceV2 { } if (included) { totalReward += - (epochRewards[i] * (1000 - shareRateOf[msg.sender])) / + (epochRewards[i + 1] * (1000 - shareRateOf[msg.sender])) / 7 / 1000; } @@ -278,7 +296,12 @@ contract GovernanceV2 is IGovernanceV2 { } function getCurrentConsensus() public view returns (address[7] memory) { - return getConsensus(getRealCurrentEpoch() - 1); + uint epoch = getRealCurrentEpoch(); + if (epoch > 0) { + return getConsensus(epoch - 1); + } else { + return getConsensus(epoch); + } } function getConsensus(uint epoch) public view returns (address[7] memory) { From e3cefd57c5736bc6674daa9b23e6898c7bff56f6 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Wed, 6 Mar 2024 18:00:25 +0800 Subject: [PATCH 15/66] fix candidate claim --- contracts/solidity/GovernanceV2.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index d08f3f3f74..5829930118 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -71,7 +71,7 @@ contract GovernanceV2 is IGovernanceV2 { // candidate=>epoch=>amount mapping(address => mapping(uint => uint)) public receivedVotes; // candidate=>epoch - mapping(address => uint) public lastClaimedEpochOf; + mapping(address => uint) public claimStartEpochOf; // epoch=>consensus mapping(uint => address[7]) private consensusCache; @@ -154,7 +154,7 @@ contract GovernanceV2 is IGovernanceV2 { shareRateOf[msg.sender] = shareRate; candidateBalanceOf[msg.sender] = msg.value; // set the start point for claim - lastClaimedEpochOf[msg.sender] = getRealCurrentEpoch(); + claimStartEpochOf[msg.sender] = getRealCurrentEpoch(); emit Register(msg.sender); } @@ -267,11 +267,11 @@ contract GovernanceV2 is IGovernanceV2 { ); // use epochCount, to lock rewards until epoch change uint currentEpoch = getRealCurrentEpoch(); - require(currentEpoch > 2, "claim not started"); + require(currentEpoch > 1, "claim not started"); uint totalReward = 0; // loop all unclaimed epochs for ( - uint i = lastClaimedEpochOf[msg.sender] + 1; + uint i = claimStartEpochOf[msg.sender]; i < currentEpoch - 1; i++ ) { @@ -290,7 +290,7 @@ contract GovernanceV2 is IGovernanceV2 { 1000; } } - lastClaimedEpochOf[msg.sender] = currentEpoch - 2; + claimStartEpochOf[msg.sender] = currentEpoch - 1; _safeTransferETH(msg.sender, totalReward); emit CandidateClaim(msg.sender, totalReward); } From 8ab0cc9449749ef5a71c67828294ec16d5803447 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Thu, 7 Mar 2024 17:41:56 +0800 Subject: [PATCH 16/66] use topk instead of quicksort --- contracts/solidity/GovernanceV2.sol | 62 +++++++++++++++++------------ 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 5829930118..90af9dee8a 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -334,8 +334,8 @@ contract GovernanceV2 is IGovernanceV2 { votes[i] = receivedVotes[candidateList[i]][epoch]; } - // sort based on votes - _quickSort(candidates, votes, 0, int(length - 1)); + // sort top 7 based on votes + _topK(candidates, votes, 7); // return the first 7 candidates as consensus list address[7] memory consensus; @@ -350,34 +350,44 @@ contract GovernanceV2 is IGovernanceV2 { require(success, "safeTransferETH: ETH transfer failed"); } - // sort candidates from high votes to low - function _quickSort( + function _topK( address[] memory candidates, uint[] memory votes, - int left, - int right + uint k ) internal pure { - int i = left; - int j = right; - if (i == j) return; - uint pivot = votes[uint(left + (right - left) / 2)]; - while (i <= j) { - while (votes[uint(i)] > pivot) i++; - while (pivot > votes[uint(j)]) j--; - if (i <= j) { - (votes[uint(i)], votes[uint(j)]) = ( - votes[uint(j)], - votes[uint(i)] - ); - (candidates[uint(i)], candidates[uint(j)]) = ( - candidates[uint(j)], - candidates[uint(i)] - ); - i++; - j--; + uint length = candidates.length; + for (int j = int(k) / 2 - 1; j >= 0; j--) { + _heapDown(candidates, votes, uint(j), k); + } + for (uint i = k; i < length; i++) { + if (votes[i] > votes[0]) { + votes[0] = votes[i]; + candidates[0] = candidates[i]; + (votes[0], votes[i]) = (votes[i], votes[0]); + (candidates[0], candidates[i]) = (candidates[i], candidates[0]); + _heapDown(candidates, votes, 0, k); + } + } + } + + function _heapDown( + address[] memory candidates, + uint[] memory votes, + uint j, + uint k + ) internal pure { + uint i = 2 * j + 1; + while (i < k) { + if (i + 1 < k && votes[i] > votes[i + 1]) { + i += 1; + } + if (votes[i] > votes[j]) { + break; } + (votes[i], votes[j]) = (votes[j], votes[i]); + (candidates[i], candidates[j]) = (candidates[j], candidates[i]); + j = i; + i = i * 2 + 1; } - if (left < j) _quickSort(candidates, votes, left, j); - if (i < right) _quickSort(candidates, votes, i, right); } } From 5376de0461b53bc6ddb5226032881ea42dc2ab8b Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Thu, 7 Mar 2024 17:50:54 +0800 Subject: [PATCH 17/66] remove duplicated codes --- contracts/solidity/GovernanceV2.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 90af9dee8a..56edb2559f 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -363,8 +363,6 @@ contract GovernanceV2 is IGovernanceV2 { if (votes[i] > votes[0]) { votes[0] = votes[i]; candidates[0] = candidates[i]; - (votes[0], votes[i]) = (votes[i], votes[0]); - (candidates[0], candidates[i]) = (candidates[i], candidates[0]); _heapDown(candidates, votes, 0, k); } } From e3e34e074a40335d533bb364e0fd9b4f0d782180 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Thu, 7 Mar 2024 18:06:42 +0800 Subject: [PATCH 18/66] update initial consensus --- contracts/solidity/GovernanceV2.sol | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 56edb2559f..665307605c 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -77,13 +77,13 @@ contract GovernanceV2 is IGovernanceV2 { constructor() { address[7] memory initialConsensus = [ - address(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266), - address(0x70997970C51812dc3A010C7d01b50e0d17dc79C8), - address(0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC), - address(0x90F79bf6EB2c4f870365E785982E1f101E93b906), - address(0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65), - address(0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc), - address(0x976EA74026E726554dB657fA54763abd0C3a0aa9) + address(0x74f4EFFb0B538BAec703346b03B6d9292f53A4CD), + address(0x910AD1641B7125Eff746acCdCa1F11148b22f472), + address(0xfEf5F250aF14DF73f983cAAb7b1F5002189c42E0), + address(0xc51964013acbC6b271FEeCB0feBD9E7A01202930), + address(0xC5bbD9652546BC96bE3DEc97a38eE335f7873Dfa), + address(0x26F1794B81dF2B832545b8B6bbcA196b82E4fEB1), + address(0x0B51369D02e47EE3f143391B837Aa08c31AAA19b) ]; consensusCache[0] = initialConsensus; } From 31daaeae734aa1daa398d8586ac583e57211d53f Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Fri, 8 Mar 2024 11:56:28 +0800 Subject: [PATCH 19/66] change registerTime to registerEpoch, optimize array usage --- contracts/solidity/GovernanceV2.sol | 51 +++++++++++++++++++---------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 665307605c..0bcce41d39 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -54,10 +54,10 @@ contract GovernanceV2 is IGovernanceV2 { address[] public candidateList; // settings about how much reward given to voter mapping(address => uint) public shareRateOf; - // timestamp when register happens - mapping(address => uint) public registerTimeOf; - // the timestamp when exit happens - mapping(address => uint) public exitTimeOf; + // the timestamp when register happens + mapping(address => uint) public registerEpochOf; + // the epoch when exit happens + mapping(address => uint) public exitEpochOf; // the left register fee to exit mapping(address => uint) public candidateBalanceOf; // epoch=>uint @@ -149,31 +149,52 @@ contract GovernanceV2 is IGovernanceV2 { // add to candidates candidateList.push(msg.sender); } + uint epoch = _getAndUpdateEpochCount(); // record register time, share rate and balance - registerTimeOf[msg.sender] = block.timestamp; + registerEpochOf[msg.sender] = epoch; shareRateOf[msg.sender] = shareRate; candidateBalanceOf[msg.sender] = msg.value; // set the start point for claim - claimStartEpochOf[msg.sender] = getRealCurrentEpoch(); + claimStartEpochOf[msg.sender] = epoch; emit Register(msg.sender); } function exitCandidate() external { - require(registerTimeOf[msg.sender] > 0, "candidate not exists"); + require(registerEpochOf[msg.sender] > 0, "candidate not exists"); // delete register time, cannot be voted - delete registerTimeOf[msg.sender]; + delete registerEpochOf[msg.sender]; // record exit time, but candidate list not removed, balance still locked - exitTimeOf[msg.sender] = block.timestamp; + exitEpochOf[msg.sender] = _getAndUpdateEpochCount(); emit Exit(msg.sender); } function claimRegisterFee() external { // require 2 epochs to exit candidate list, so that the last round of vote can work as expected + uint epoch = _getAndUpdateEpochCount(); require( - block.timestamp > exitTimeOf[msg.sender] + 2 * EPOCH_DURATION, + epoch > exitEpochOf[msg.sender] + 1, "claim not allowed" ); + // make sure all consensus are settled + for ( + uint i = claimStartEpochOf[msg.sender]; + i < epoch - 1; + i++ + ) { + _tryGetAndCacheConsensus(i); + } + + // reorg candidate list + address[] memory candidates = candidateList; + uint length = candidateList.length; + delete candidateList; + for (uint i = 0; i < length; i++) { + if (candidates[i] != msg.sender) { + candidateList.push(candidates[i]); + } + } + // send back balance uint amount = candidateBalanceOf[msg.sender]; delete candidateBalanceOf[msg.sender]; @@ -182,7 +203,7 @@ contract GovernanceV2 is IGovernanceV2 { function vote(address candidateTo) external payable { require(msg.value >= MIN_VOTE_AMOUNT, "insufficient amount"); - require(registerTimeOf[candidateTo] > 0, "candidate not allowed"); + require(registerEpochOf[candidateTo] > 0, "candidate not allowed"); // the first person vote in new epoch will pay for update uint currentEpoch = _getAndUpdateEpochCount(); @@ -218,7 +239,7 @@ contract GovernanceV2 is IGovernanceV2 { function voterWithdraw() external { // use epochCount, to lock votes and rewards until epoch change - uint currentEpoch = getRealCurrentEpoch(); + uint currentEpoch = _getAndUpdateEpochCount(); uint totalAmount = 0; uint totalReward = 0; // loop all voted epochs @@ -261,12 +282,8 @@ contract GovernanceV2 is IGovernanceV2 { } function candidateClaim() external { - require( - registerTimeOf[msg.sender] > 0 || exitTimeOf[msg.sender] > 0, - "not a candidate" - ); // use epochCount, to lock rewards until epoch change - uint currentEpoch = getRealCurrentEpoch(); + uint currentEpoch = _getAndUpdateEpochCount(); require(currentEpoch > 1, "claim not started"); uint totalReward = 0; // loop all unclaimed epochs From d875c4eacf9d045b30811c17d56d67d9311f7d31 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Fri, 8 Mar 2024 12:07:59 +0800 Subject: [PATCH 20/66] fix register --- contracts/solidity/GovernanceV2.sol | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 0bcce41d39..7f586f9104 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -138,17 +138,13 @@ contract GovernanceV2 is IGovernanceV2 { address[] memory list = candidateList; uint length = candidateList.length; // check duplication - bool existed = false; for (uint i = 0; i < length; i++) { if (list[i] == msg.sender) { - existed = true; - break; + revert("candidate exists"); } } - if (!existed) { - // add to candidates - candidateList.push(msg.sender); - } + candidateList.push(msg.sender); + uint epoch = _getAndUpdateEpochCount(); // record register time, share rate and balance registerEpochOf[msg.sender] = epoch; From 4bd1e18767717038040cf5e1f51aca8b280a4d57 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Mon, 11 Mar 2024 10:52:20 +0800 Subject: [PATCH 21/66] prevent error in getConsensus() --- contracts/solidity/GovernanceV2.sol | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 7f586f9104..52a41633c6 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -341,9 +341,9 @@ contract GovernanceV2 is IGovernanceV2 { ) internal view returns (address[7] memory) { // build up a votes array address[] memory candidates = candidateList; - uint length = candidateList.length; - uint[] memory votes = new uint[](length); - for (uint i = 0; i < length; i++) { + uint candidateLength = candidateList.length; + uint[] memory votes = new uint[](candidateLength); + for (uint i = 0; i < candidateLength; i++) { votes[i] = receivedVotes[candidateList[i]][epoch]; } @@ -352,7 +352,8 @@ contract GovernanceV2 is IGovernanceV2 { // return the first 7 candidates as consensus list address[7] memory consensus; - for (uint i = 0; i < 7; i++) { + uint size = candidateLength > 7 ? 7 : candidateLength; + for (uint i = 0; i < size; i++) { consensus[i] = candidates[i]; } return consensus; @@ -369,6 +370,9 @@ contract GovernanceV2 is IGovernanceV2 { uint k ) internal pure { uint length = candidates.length; + if (length <= k) { + return; + } for (int j = int(k) / 2 - 1; j >= 0; j--) { _heapDown(candidates, votes, uint(j), k); } From 3bed6606982d2e474350750f3c273df25dbf854f Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Mon, 11 Mar 2024 11:51:53 +0800 Subject: [PATCH 22/66] add min amout requirement for change epoch --- contracts/solidity/GovernanceV2.sol | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 52a41633c6..ca6ad015f3 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -40,6 +40,8 @@ contract GovernanceV2 is IGovernanceV2 { uint public constant MIN_VOTE_AMOUNT = 1 ether; // register fee uint public constant REGISTER_FEE = 1000 ether; + // the min vote amount to change epoch + uint public constant MIN_TOTAL_VOTE = 3000000 ether; // minimum duration of an epoch uint public constant EPOCH_DURATION = 1209600; // GovReward contract @@ -70,6 +72,8 @@ contract GovernanceV2 is IGovernanceV2 { mapping(address => uint[]) public unclaimedEpochsOf; // candidate=>epoch=>amount mapping(address => mapping(uint => uint)) public receivedVotes; + // epoch=>amount + mapping(uint => uint) public totalVotes; // candidate=>epoch mapping(address => uint) public claimStartEpochOf; // epoch=>consensus @@ -110,7 +114,7 @@ contract GovernanceV2 is IGovernanceV2 { } function _getAndUpdateEpochCount() internal returns (uint) { - if (block.timestamp > lastEpochTime + EPOCH_DURATION) { + if ((block.timestamp > lastEpochTime + EPOCH_DURATION && totalVotes[epochCount] >= MIN_TOTAL_VOTE) || epochCount == 0) { IGovReward(govReward).withdraw(); epochCount += 1; lastEpochTime = block.timestamp; @@ -216,6 +220,7 @@ contract GovernanceV2 is IGovernanceV2 { } votedAmount[msg.sender][currentEpoch] = voted + msg.value; receivedVotes[candidateTo][currentEpoch] += msg.value; + totalVotes[currentEpoch] += msg.value; emit Vote(msg.sender, candidateTo, msg.value); } @@ -226,6 +231,7 @@ contract GovernanceV2 is IGovernanceV2 { address candidateFrom = votedTo[msg.sender][currentEpoch]; uint amount = votedAmount[msg.sender][currentEpoch]; receivedVotes[candidateFrom][currentEpoch] -= amount; + totalVotes[currentEpoch] -= amount; delete votedTo[msg.sender][currentEpoch]; delete votedAmount[msg.sender][currentEpoch]; _safeTransferETH(msg.sender, amount); From b0bdc8c9e0dde0555509d58fbe3fb6b014e9a981 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Mon, 11 Mar 2024 15:27:40 +0800 Subject: [PATCH 23/66] add min candidates requirement for change epoch, revert 4bd1e18 --- contracts/solidity/GovernanceV2.sol | 53 +++++++++++++++++------------ 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index ca6ad015f3..ce4c339f3d 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -29,6 +29,9 @@ interface IGovernanceV2 { // claim rewards for being a consensus member function candidateClaim() external; + + // get the current selected consensus group + function getCurrentConsensus() external returns (address[7] memory); } interface IGovReward { @@ -54,6 +57,14 @@ contract GovernanceV2 is IGovernanceV2 { uint public lastEpochTime; // candidate list address[] public candidateList; + // epoch=>uint + mapping(uint => uint) public epochRewards; + // epoch=>amount + mapping(uint => uint) public totalVotes; + // epoch=>amount + mapping(uint => uint) public votedCandidates; + // epoch=>consensus + mapping(uint => address[7]) private consensusCache; // settings about how much reward given to voter mapping(address => uint) public shareRateOf; // the timestamp when register happens @@ -62,22 +73,16 @@ contract GovernanceV2 is IGovernanceV2 { mapping(address => uint) public exitEpochOf; // the left register fee to exit mapping(address => uint) public candidateBalanceOf; - // epoch=>uint - mapping(uint => uint) public epochRewards; + // candidate=>epoch + mapping(address => uint) public claimStartEpochOf; + // candidate=>epoch=>amount + mapping(address => mapping(uint => uint)) public receivedVotes; // voter=>epoch=>candidate mapping(address => mapping(uint => address)) public votedTo; // voter=>epoch=>amount mapping(address => mapping(uint => uint)) public votedAmount; // voter=>epochs mapping(address => uint[]) public unclaimedEpochsOf; - // candidate=>epoch=>amount - mapping(address => mapping(uint => uint)) public receivedVotes; - // epoch=>amount - mapping(uint => uint) public totalVotes; - // candidate=>epoch - mapping(address => uint) public claimStartEpochOf; - // epoch=>consensus - mapping(uint => address[7]) private consensusCache; constructor() { address[7] memory initialConsensus = [ @@ -114,7 +119,7 @@ contract GovernanceV2 is IGovernanceV2 { } function _getAndUpdateEpochCount() internal returns (uint) { - if ((block.timestamp > lastEpochTime + EPOCH_DURATION && totalVotes[epochCount] >= MIN_TOTAL_VOTE) || epochCount == 0) { + if ((block.timestamp > lastEpochTime + EPOCH_DURATION && totalVotes[epochCount] >= MIN_TOTAL_VOTE && votedCandidates[epochCount] >= 7) || epochCount == 0) { IGovReward(govReward).withdraw(); epochCount += 1; lastEpochTime = block.timestamp; @@ -219,7 +224,12 @@ contract GovernanceV2 is IGovernanceV2 { ); } votedAmount[msg.sender][currentEpoch] = voted + msg.value; - receivedVotes[candidateTo][currentEpoch] += msg.value; + + uint received = receivedVotes[candidateTo][currentEpoch]; + if (received == 0) { + votedCandidates[currentEpoch] += 1; + } + receivedVotes[candidateTo][currentEpoch] = received + msg.value; totalVotes[currentEpoch] += msg.value; emit Vote(msg.sender, candidateTo, msg.value); @@ -230,7 +240,12 @@ contract GovernanceV2 is IGovernanceV2 { uint currentEpoch = getNominalCurrentEpoch(); address candidateFrom = votedTo[msg.sender][currentEpoch]; uint amount = votedAmount[msg.sender][currentEpoch]; - receivedVotes[candidateFrom][currentEpoch] -= amount; + + uint received = receivedVotes[candidateFrom][currentEpoch]; + if (received == amount) { + votedCandidates[currentEpoch] -= 1; + } + receivedVotes[candidateFrom][currentEpoch] = received - amount; totalVotes[currentEpoch] -= amount; delete votedTo[msg.sender][currentEpoch]; delete votedAmount[msg.sender][currentEpoch]; @@ -347,9 +362,9 @@ contract GovernanceV2 is IGovernanceV2 { ) internal view returns (address[7] memory) { // build up a votes array address[] memory candidates = candidateList; - uint candidateLength = candidateList.length; - uint[] memory votes = new uint[](candidateLength); - for (uint i = 0; i < candidateLength; i++) { + uint length = candidateList.length; + uint[] memory votes = new uint[](length); + for (uint i = 0; i < length; i++) { votes[i] = receivedVotes[candidateList[i]][epoch]; } @@ -358,8 +373,7 @@ contract GovernanceV2 is IGovernanceV2 { // return the first 7 candidates as consensus list address[7] memory consensus; - uint size = candidateLength > 7 ? 7 : candidateLength; - for (uint i = 0; i < size; i++) { + for (uint i = 0; i < 7; i++) { consensus[i] = candidates[i]; } return consensus; @@ -376,9 +390,6 @@ contract GovernanceV2 is IGovernanceV2 { uint k ) internal pure { uint length = candidates.length; - if (length <= k) { - return; - } for (int j = int(k) / 2 - 1; j >= 0; j--) { _heapDown(candidates, votes, uint(j), k); } From 4670ecfed5109f80c63ecc826aaac326a6d5c652 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 12 Mar 2024 10:47:22 +0800 Subject: [PATCH 24/66] use EnumerableSet --- contracts/solidity/GovernanceV2.sol | 36 ++++++++++++----------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index ce4c339f3d..f7dd6dc248 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; + interface IGovernanceV2 { event Register(address candidate); event Exit(address candidate); @@ -39,6 +41,8 @@ interface IGovReward { } contract GovernanceV2 is IGovernanceV2 { + using EnumerableSet for EnumerableSet.AddressSet; + // the min balance for voting uint public constant MIN_VOTE_AMOUNT = 1 ether; // register fee @@ -56,7 +60,7 @@ contract GovernanceV2 is IGovernanceV2 { // timestamp of the last time when voting starts uint public lastEpochTime; // candidate list - address[] public candidateList; + EnumerableSet.AddressSet internal candidateList; // epoch=>uint mapping(uint => uint) public epochRewards; // epoch=>amount @@ -141,18 +145,15 @@ contract GovernanceV2 is IGovernanceV2 { return receivedVotes[candidate][epoch]; } + function getCandidates() public view returns (address[] memory) { + return candidateList.values(); + } + function registerCandidate(uint shareRate) external payable { require(msg.value == REGISTER_FEE, "insufficient amount"); require(shareRate < 1000, "invalid rate"); - address[] memory list = candidateList; - uint length = candidateList.length; - // check duplication - for (uint i = 0; i < length; i++) { - if (list[i] == msg.sender) { - revert("candidate exists"); - } - } - candidateList.push(msg.sender); + require(!candidateList.contains(msg.sender), "candidate exists"); + candidateList.add(msg.sender); uint epoch = _getAndUpdateEpochCount(); // record register time, share rate and balance @@ -191,14 +192,7 @@ contract GovernanceV2 is IGovernanceV2 { } // reorg candidate list - address[] memory candidates = candidateList; - uint length = candidateList.length; - delete candidateList; - for (uint i = 0; i < length; i++) { - if (candidates[i] != msg.sender) { - candidateList.push(candidates[i]); - } - } + candidateList.remove(msg.sender); // send back balance uint amount = candidateBalanceOf[msg.sender]; @@ -361,11 +355,11 @@ contract GovernanceV2 is IGovernanceV2 { uint epoch ) internal view returns (address[7] memory) { // build up a votes array - address[] memory candidates = candidateList; - uint length = candidateList.length; + address[] memory candidates = getCandidates(); + uint length = candidates.length; uint[] memory votes = new uint[](length); for (uint i = 0; i < length; i++) { - votes[i] = receivedVotes[candidateList[i]][epoch]; + votes[i] = receivedVotes[candidates[i]][epoch]; } // sort top 7 based on votes From c8396b226821682f52cb12841cae3018df07e17b Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 12 Mar 2024 11:23:41 +0800 Subject: [PATCH 25/66] allow other size for consensus --- contracts/solidity/GovernanceV2.sol | 71 ++++++++++++++--------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index f7dd6dc248..50e3c3bb93 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; interface IGovernanceV2 { event Register(address candidate); @@ -33,7 +33,7 @@ interface IGovernanceV2 { function candidateClaim() external; // get the current selected consensus group - function getCurrentConsensus() external returns (address[7] memory); + function getCurrentConsensus() external returns (address[] memory); } interface IGovReward { @@ -43,11 +43,12 @@ interface IGovReward { contract GovernanceV2 is IGovernanceV2 { using EnumerableSet for EnumerableSet.AddressSet; + uint public constant CONSENSUS_SIZE = 7; // the min balance for voting uint public constant MIN_VOTE_AMOUNT = 1 ether; // register fee uint public constant REGISTER_FEE = 1000 ether; - // the min vote amount to change epoch + // the min vote amount to change epoch uint public constant MIN_TOTAL_VOTE = 3000000 ether; // minimum duration of an epoch uint public constant EPOCH_DURATION = 1209600; @@ -68,7 +69,7 @@ contract GovernanceV2 is IGovernanceV2 { // epoch=>amount mapping(uint => uint) public votedCandidates; // epoch=>consensus - mapping(uint => address[7]) private consensusCache; + mapping(uint => address[]) private consensusCache; // settings about how much reward given to voter mapping(address => uint) public shareRateOf; // the timestamp when register happens @@ -123,7 +124,12 @@ contract GovernanceV2 is IGovernanceV2 { } function _getAndUpdateEpochCount() internal returns (uint) { - if ((block.timestamp > lastEpochTime + EPOCH_DURATION && totalVotes[epochCount] >= MIN_TOTAL_VOTE && votedCandidates[epochCount] >= 7) || epochCount == 0) { + if ( + (block.timestamp > lastEpochTime + EPOCH_DURATION && + totalVotes[epochCount] >= MIN_TOTAL_VOTE && + votedCandidates[epochCount] >= CONSENSUS_SIZE) || + epochCount == 0 + ) { IGovReward(govReward).withdraw(); epochCount += 1; lastEpochTime = block.timestamp; @@ -177,17 +183,10 @@ contract GovernanceV2 is IGovernanceV2 { function claimRegisterFee() external { // require 2 epochs to exit candidate list, so that the last round of vote can work as expected uint epoch = _getAndUpdateEpochCount(); - require( - epoch > exitEpochOf[msg.sender] + 1, - "claim not allowed" - ); + require(epoch > exitEpochOf[msg.sender] + 1, "claim not allowed"); // make sure all consensus are settled - for ( - uint i = claimStartEpochOf[msg.sender]; - i < epoch - 1; - i++ - ) { + for (uint i = claimStartEpochOf[msg.sender]; i < epoch - 1; i++) { _tryGetAndCacheConsensus(i); } @@ -267,9 +266,9 @@ contract GovernanceV2 is IGovernanceV2 { // calculate reward address candidate = votedTo[msg.sender][epoch]; - address[7] memory consensus = _tryGetAndCacheConsensus(epoch); + address[] memory consensus = _tryGetAndCacheConsensus(epoch); bool included = false; - for (uint j = 0; j < 7; j++) { + for (uint j = 0; j < CONSENSUS_SIZE; j++) { if (consensus[j] == candidate) { included = true; } @@ -280,7 +279,7 @@ contract GovernanceV2 is IGovernanceV2 { epochRewards[epoch + 1] * shareRateOf[candidate]) / receivedVotes[candidate][epoch] / - 7 / + CONSENSUS_SIZE / 1000; } } else if (epoch >= currentEpoch - 1) { @@ -304,9 +303,9 @@ contract GovernanceV2 is IGovernanceV2 { i++ ) { // only epochs before the current running one (the one before current voting) - address[7] memory consensus = _tryGetAndCacheConsensus(i); + address[] memory consensus = _tryGetAndCacheConsensus(i); bool included = false; - for (uint j = 0; j < 7; j++) { + for (uint j = 0; j < CONSENSUS_SIZE; j++) { if (consensus[j] == msg.sender) { included = true; } @@ -314,7 +313,7 @@ contract GovernanceV2 is IGovernanceV2 { if (included) { totalReward += (epochRewards[i + 1] * (1000 - shareRateOf[msg.sender])) / - 7 / + CONSENSUS_SIZE / 1000; } } @@ -323,7 +322,7 @@ contract GovernanceV2 is IGovernanceV2 { emit CandidateClaim(msg.sender, totalReward); } - function getCurrentConsensus() public view returns (address[7] memory) { + function getCurrentConsensus() public view returns (address[] memory) { uint epoch = getRealCurrentEpoch(); if (epoch > 0) { return getConsensus(epoch - 1); @@ -332,28 +331,28 @@ contract GovernanceV2 is IGovernanceV2 { } } - function getConsensus(uint epoch) public view returns (address[7] memory) { - address[7] memory cache = consensusCache[epoch]; - if (cache[0] == address(0)) { - return _getConsensus(epoch); + function getConsensus(uint epoch) public view returns (address[] memory) { + address[] memory cache = consensusCache[epoch]; + if (cache.length == 0) { + return _computeConsensus(epoch); } return cache; } function _tryGetAndCacheConsensus( uint epoch - ) internal returns (address[7] memory) { - address[7] memory cache = consensusCache[epoch]; - if (cache[0] == address(0)) { - cache = _getConsensus(epoch); + ) internal returns (address[] memory) { + address[] memory cache = consensusCache[epoch]; + if (cache.length == 0) { + cache = _computeConsensus(epoch); consensusCache[epoch] = cache; } return cache; } - function _getConsensus( + function _computeConsensus( uint epoch - ) internal view returns (address[7] memory) { + ) internal view returns (address[] memory) { // build up a votes array address[] memory candidates = getCandidates(); uint length = candidates.length; @@ -362,12 +361,12 @@ contract GovernanceV2 is IGovernanceV2 { votes[i] = receivedVotes[candidates[i]][epoch]; } - // sort top 7 based on votes - _topK(candidates, votes, 7); + // sort top CONSENSUS_SIZE based on votes + _topK(candidates, votes, CONSENSUS_SIZE); - // return the first 7 candidates as consensus list - address[7] memory consensus; - for (uint i = 0; i < 7; i++) { + // return the first CONSENSUS_SIZE candidates as consensus list + address[] memory consensus = new address[](CONSENSUS_SIZE); + for (uint i = 0; i < CONSENSUS_SIZE; i++) { consensus[i] = candidates[i]; } return consensus; From 3a1191b2a6258e75be8661437a86c423aff9f266 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 12 Mar 2024 15:49:57 +0800 Subject: [PATCH 26/66] use block height instead of timestamp --- contracts/solidity/GovernanceV2.sol | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 50e3c3bb93..1ddb0abcf0 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -50,16 +50,16 @@ contract GovernanceV2 is IGovernanceV2 { uint public constant REGISTER_FEE = 1000 ether; // the min vote amount to change epoch uint public constant MIN_TOTAL_VOTE = 3000000 ether; - // minimum duration of an epoch - uint public constant EPOCH_DURATION = 1209600; + // minimum duration of an epoch (in blocks) + uint public constant EPOCH_DURATION = 120960; // GovReward contract address public constant govReward = 0x1212000000000000000000000000000000000003; // counter of epoch index uint public epochCount; - // timestamp of the last time when voting starts - uint public lastEpochTime; + // the last block height when voting starts + uint public lastEpochHeight; // candidate list EnumerableSet.AddressSet internal candidateList; // epoch=>uint @@ -112,7 +112,7 @@ contract GovernanceV2 is IGovernanceV2 { } function getNominalCurrentEpoch() public view returns (uint) { - if (block.timestamp > lastEpochTime + EPOCH_DURATION) { + if (block.number > lastEpochHeight + EPOCH_DURATION) { return epochCount + 1; } else { return epochCount; @@ -125,14 +125,14 @@ contract GovernanceV2 is IGovernanceV2 { function _getAndUpdateEpochCount() internal returns (uint) { if ( - (block.timestamp > lastEpochTime + EPOCH_DURATION && + (block.number > lastEpochHeight + EPOCH_DURATION && totalVotes[epochCount] >= MIN_TOTAL_VOTE && votedCandidates[epochCount] >= CONSENSUS_SIZE) || epochCount == 0 ) { IGovReward(govReward).withdraw(); epochCount += 1; - lastEpochTime = block.timestamp; + lastEpochHeight = block.number; } return epochCount; } From c018f7857302656c323775e3f78cd601bde7ac86 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 12 Mar 2024 17:13:09 +0800 Subject: [PATCH 27/66] fix epoch 0 --- contracts/solidity/GovernanceV2.sol | 32 +++++++++-------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 1ddb0abcf0..2df8f9b437 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -57,9 +57,9 @@ contract GovernanceV2 is IGovernanceV2 { 0x1212000000000000000000000000000000000003; // counter of epoch index - uint public epochCount; + uint public epochCount = 1; // the last block height when voting starts - uint public lastEpochHeight; + uint public lastEpochHeight = block.number; // candidate list EnumerableSet.AddressSet internal candidateList; // epoch=>uint @@ -90,7 +90,7 @@ contract GovernanceV2 is IGovernanceV2 { mapping(address => uint[]) public unclaimedEpochsOf; constructor() { - address[7] memory initialConsensus = [ + consensusCache[0] = [ address(0x74f4EFFb0B538BAec703346b03B6d9292f53A4CD), address(0x910AD1641B7125Eff746acCdCa1F11148b22f472), address(0xfEf5F250aF14DF73f983cAAb7b1F5002189c42E0), @@ -99,16 +99,10 @@ contract GovernanceV2 is IGovernanceV2 { address(0x26F1794B81dF2B832545b8B6bbcA196b82E4fEB1), address(0x0B51369D02e47EE3f143391B837Aa08c31AAA19b) ]; - consensusCache[0] = initialConsensus; } receive() external payable { - uint epoch = getRealCurrentEpoch(); - if (epoch > 0) { - epochRewards[epoch] += msg.value; - } else { - epochRewards[epoch + 1] += msg.value; - } + epochRewards[getRealCurrentEpoch()] += msg.value; } function getNominalCurrentEpoch() public view returns (uint) { @@ -125,10 +119,9 @@ contract GovernanceV2 is IGovernanceV2 { function _getAndUpdateEpochCount() internal returns (uint) { if ( - (block.number > lastEpochHeight + EPOCH_DURATION && - totalVotes[epochCount] >= MIN_TOTAL_VOTE && - votedCandidates[epochCount] >= CONSENSUS_SIZE) || - epochCount == 0 + block.number > lastEpochHeight + EPOCH_DURATION && + totalVotes[epochCount] >= MIN_TOTAL_VOTE && + votedCandidates[epochCount] >= CONSENSUS_SIZE ) { IGovReward(govReward).withdraw(); epochCount += 1; @@ -166,8 +159,8 @@ contract GovernanceV2 is IGovernanceV2 { registerEpochOf[msg.sender] = epoch; shareRateOf[msg.sender] = shareRate; candidateBalanceOf[msg.sender] = msg.value; - // set the start point for claim - claimStartEpochOf[msg.sender] = epoch; + // set the start point for claim, only if register in epoch 1 can get epoch 0 reward + claimStartEpochOf[msg.sender] = epoch > 1 ? epoch : 0; emit Register(msg.sender); } @@ -323,12 +316,7 @@ contract GovernanceV2 is IGovernanceV2 { } function getCurrentConsensus() public view returns (address[] memory) { - uint epoch = getRealCurrentEpoch(); - if (epoch > 0) { - return getConsensus(epoch - 1); - } else { - return getConsensus(epoch); - } + return getConsensus(getRealCurrentEpoch() - 1); } function getConsensus(uint epoch) public view returns (address[] memory) { From 057d307f3fd8bf3a34f80c27bb06653bd3695f31 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 12 Mar 2024 18:00:54 +0800 Subject: [PATCH 28/66] change lazy cache to immediate update --- contracts/solidity/GovernanceV2.sol | 46 ++++++++--------------------- 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 2df8f9b437..d6a661fc9e 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -69,7 +69,7 @@ contract GovernanceV2 is IGovernanceV2 { // epoch=>amount mapping(uint => uint) public votedCandidates; // epoch=>consensus - mapping(uint => address[]) private consensusCache; + mapping(uint => address[]) public consensusOf; // settings about how much reward given to voter mapping(address => uint) public shareRateOf; // the timestamp when register happens @@ -90,7 +90,7 @@ contract GovernanceV2 is IGovernanceV2 { mapping(address => uint[]) public unclaimedEpochsOf; constructor() { - consensusCache[0] = [ + consensusOf[0] = [ address(0x74f4EFFb0B538BAec703346b03B6d9292f53A4CD), address(0x910AD1641B7125Eff746acCdCa1F11148b22f472), address(0xfEf5F250aF14DF73f983cAAb7b1F5002189c42E0), @@ -118,16 +118,20 @@ contract GovernanceV2 is IGovernanceV2 { } function _getAndUpdateEpochCount() internal returns (uint) { + uint epoch = epochCount; if ( block.number > lastEpochHeight + EPOCH_DURATION && - totalVotes[epochCount] >= MIN_TOTAL_VOTE && - votedCandidates[epochCount] >= CONSENSUS_SIZE + totalVotes[epoch] >= MIN_TOTAL_VOTE && + votedCandidates[epoch] >= CONSENSUS_SIZE ) { + // record gov reward and vote result IGovReward(govReward).withdraw(); - epochCount += 1; + consensusOf[epoch] = _computeConsensus(epoch); + epoch += 1; + epochCount = epoch; lastEpochHeight = block.number; } - return epochCount; + return epoch; } function getVotedByEpoch( @@ -178,11 +182,6 @@ contract GovernanceV2 is IGovernanceV2 { uint epoch = _getAndUpdateEpochCount(); require(epoch > exitEpochOf[msg.sender] + 1, "claim not allowed"); - // make sure all consensus are settled - for (uint i = claimStartEpochOf[msg.sender]; i < epoch - 1; i++) { - _tryGetAndCacheConsensus(i); - } - // reorg candidate list candidateList.remove(msg.sender); @@ -259,7 +258,7 @@ contract GovernanceV2 is IGovernanceV2 { // calculate reward address candidate = votedTo[msg.sender][epoch]; - address[] memory consensus = _tryGetAndCacheConsensus(epoch); + address[] memory consensus = consensusOf[epoch]; bool included = false; for (uint j = 0; j < CONSENSUS_SIZE; j++) { if (consensus[j] == candidate) { @@ -296,7 +295,7 @@ contract GovernanceV2 is IGovernanceV2 { i++ ) { // only epochs before the current running one (the one before current voting) - address[] memory consensus = _tryGetAndCacheConsensus(i); + address[] memory consensus = consensusOf[i]; bool included = false; for (uint j = 0; j < CONSENSUS_SIZE; j++) { if (consensus[j] == msg.sender) { @@ -316,26 +315,7 @@ contract GovernanceV2 is IGovernanceV2 { } function getCurrentConsensus() public view returns (address[] memory) { - return getConsensus(getRealCurrentEpoch() - 1); - } - - function getConsensus(uint epoch) public view returns (address[] memory) { - address[] memory cache = consensusCache[epoch]; - if (cache.length == 0) { - return _computeConsensus(epoch); - } - return cache; - } - - function _tryGetAndCacheConsensus( - uint epoch - ) internal returns (address[] memory) { - address[] memory cache = consensusCache[epoch]; - if (cache.length == 0) { - cache = _computeConsensus(epoch); - consensusCache[epoch] = cache; - } - return cache; + return consensusOf[getRealCurrentEpoch() - 1]; } function _computeConsensus( From 8ed7867b3a41db7cda87e06de08c4b87cd46389d Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Wed, 13 Mar 2024 10:11:25 +0800 Subject: [PATCH 29/66] update GovReward --- contracts/solidity/GovRewardV2.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/solidity/GovRewardV2.sol b/contracts/solidity/GovRewardV2.sol index f6f9bba607..3d863afda5 100644 --- a/contracts/solidity/GovRewardV2.sol +++ b/contracts/solidity/GovRewardV2.sol @@ -21,11 +21,11 @@ library TransferHelper { interface IGovernance { // get current consensus group - function getCurrentConsensus() external view returns (address[7] memory); + function getCurrentConsensus() external view returns (address[] memory); } interface IGovReward { - function getMiners() external view returns (address[7] memory); + function getMiners() external view returns (address[] memory); function withdraw() external; } @@ -42,7 +42,7 @@ contract GovReward is IGovReward { _; } - function getMiners() external view override returns (address[7] memory) { + function getMiners() external view override returns (address[] memory) { return IGovernance(governance).getCurrentConsensus(); } From ca4c8689002112c53e477732f1596e8e1f59ef15 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Wed, 13 Mar 2024 11:47:25 +0800 Subject: [PATCH 30/66] add dbft specific apis --- contracts/solidity/GovernanceV2.sol | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index d6a661fc9e..8e938b9432 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -34,6 +34,16 @@ interface IGovernanceV2 { // get the current selected consensus group function getCurrentConsensus() external returns (address[] memory); + + /* + The following should only be used by DBFT module, refer to https://github.com/nspcc-dev/neo-go/blob/master/pkg/core/blockchain.go + */ + + // get the consensus group before the current block is executed, which is the group that should produce this block + function getNextBlockValidators() external returns (address[] memory); + + // select the latest consensus group after the current block is executed, which is the group that should produce the next block + function computeNextBlockValidators() external returns (address[] memory); } interface IGovReward { @@ -318,6 +328,20 @@ contract GovernanceV2 is IGovernanceV2 { return consensusOf[getRealCurrentEpoch() - 1]; } + function getNextBlockValidators() external view returns (address[] memory) { + uint height = block.number; + if (lastEpochHeight == height) { + // epoch changed in this block, so this is the last block + return consensusOf[getRealCurrentEpoch() - 2]; + } else { + return consensusOf[getRealCurrentEpoch() - 1]; + } + } + + function computeNextBlockValidators() external view returns (address[] memory) { + return getCurrentConsensus(); + } + function _computeConsensus( uint epoch ) internal view returns (address[] memory) { From 5c07ff25ba07e9d6f84154db3fe55bac51df9516 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Thu, 14 Mar 2024 11:00:58 +0800 Subject: [PATCH 31/66] change epochCount getter names --- contracts/solidity/GovernanceV2.sol | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 8e938b9432..94af6eaf53 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -112,10 +112,10 @@ contract GovernanceV2 is IGovernanceV2 { } receive() external payable { - epochRewards[getRealCurrentEpoch()] += msg.value; + epochRewards[getCurrentRunningEpoch()] += msg.value; } - function getNominalCurrentEpoch() public view returns (uint) { + function getCurrentRevokingEpoch() public view returns (uint) { if (block.number > lastEpochHeight + EPOCH_DURATION) { return epochCount + 1; } else { @@ -123,10 +123,14 @@ contract GovernanceV2 is IGovernanceV2 { } } - function getRealCurrentEpoch() public view returns (uint) { + function getCurrentVotingEpoch() public view returns (uint) { return epochCount; } + function getCurrentRunningEpoch() public view returns (uint) { + return epochCount - 1; + } + function _getAndUpdateEpochCount() internal returns (uint) { uint epoch = epochCount; if ( @@ -232,7 +236,7 @@ contract GovernanceV2 is IGovernanceV2 { function revokeVote() external { // revoke will not trigger epoch change - uint currentEpoch = getNominalCurrentEpoch(); + uint currentEpoch = getCurrentRevokingEpoch(); address candidateFrom = votedTo[msg.sender][currentEpoch]; uint amount = votedAmount[msg.sender][currentEpoch]; @@ -278,7 +282,7 @@ contract GovernanceV2 is IGovernanceV2 { if (included) { totalReward += (epochAmount * - epochRewards[epoch + 1] * + epochRewards[epoch] * shareRateOf[candidate]) / receivedVotes[candidate][epoch] / CONSENSUS_SIZE / @@ -314,7 +318,7 @@ contract GovernanceV2 is IGovernanceV2 { } if (included) { totalReward += - (epochRewards[i + 1] * (1000 - shareRateOf[msg.sender])) / + (epochRewards[i] * (1000 - shareRateOf[msg.sender])) / CONSENSUS_SIZE / 1000; } @@ -325,16 +329,16 @@ contract GovernanceV2 is IGovernanceV2 { } function getCurrentConsensus() public view returns (address[] memory) { - return consensusOf[getRealCurrentEpoch() - 1]; + return consensusOf[getCurrentRunningEpoch()]; } function getNextBlockValidators() external view returns (address[] memory) { uint height = block.number; if (lastEpochHeight == height) { // epoch changed in this block, so this is the last block - return consensusOf[getRealCurrentEpoch() - 2]; + return consensusOf[getCurrentRunningEpoch() - 1]; } else { - return consensusOf[getRealCurrentEpoch() - 1]; + return consensusOf[getCurrentRunningEpoch()]; } } From 0a35b12b9ba29a05b9e6143ec2d74b90696b4277 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Thu, 14 Mar 2024 11:18:22 +0800 Subject: [PATCH 32/66] rm a comment --- contracts/solidity/GovernanceV2.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 94af6eaf53..cb770d9a82 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -66,7 +66,6 @@ contract GovernanceV2 is IGovernanceV2 { address public constant govReward = 0x1212000000000000000000000000000000000003; - // counter of epoch index uint public epochCount = 1; // the last block height when voting starts uint public lastEpochHeight = block.number; From 4308e26136d6f14379c1b22038abb4c469966a1c Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Thu, 14 Mar 2024 14:40:04 +0800 Subject: [PATCH 33/66] fix claimRegisterFee --- contracts/solidity/GovernanceV2.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index cb770d9a82..15da9576ac 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -200,6 +200,7 @@ contract GovernanceV2 is IGovernanceV2 { // send back balance uint amount = candidateBalanceOf[msg.sender]; + delete registerEpochOf[msg.sender]; delete candidateBalanceOf[msg.sender]; _safeTransferETH(msg.sender, amount); } From 435097e26f45962fec9723dfacdae89439324827 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Thu, 14 Mar 2024 15:33:03 +0800 Subject: [PATCH 34/66] fix revokeVote --- contracts/solidity/GovernanceV2.sol | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 15da9576ac..5692864981 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -115,10 +115,15 @@ contract GovernanceV2 is IGovernanceV2 { } function getCurrentRevokingEpoch() public view returns (uint) { - if (block.number > lastEpochHeight + EPOCH_DURATION) { - return epochCount + 1; + uint epoch = epochCount; + if ( + block.number > lastEpochHeight + EPOCH_DURATION && + totalVotes[epoch] >= MIN_TOTAL_VOTE && + votedCandidates[epoch] >= CONSENSUS_SIZE + ) { + return epoch + 1; } else { - return epochCount; + return epoch; } } @@ -239,6 +244,7 @@ contract GovernanceV2 is IGovernanceV2 { uint currentEpoch = getCurrentRevokingEpoch(); address candidateFrom = votedTo[msg.sender][currentEpoch]; uint amount = votedAmount[msg.sender][currentEpoch]; + require(amount > 0, "insufficient amount"); uint received = receivedVotes[candidateFrom][currentEpoch]; if (received == amount) { From 04d19f42eaf10940cdbc34083568dcb9bf4e4e88 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Thu, 14 Mar 2024 15:53:50 +0800 Subject: [PATCH 35/66] revert 4308e26 --- contracts/solidity/GovernanceV2.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 5692864981..c0768e8a4e 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -205,7 +205,6 @@ contract GovernanceV2 is IGovernanceV2 { // send back balance uint amount = candidateBalanceOf[msg.sender]; - delete registerEpochOf[msg.sender]; delete candidateBalanceOf[msg.sender]; _safeTransferETH(msg.sender, amount); } From df5c1074ee45ea3eacc58e51663c55a3c50e7efe Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Thu, 14 Mar 2024 15:58:39 +0800 Subject: [PATCH 36/66] fix registerCandidate --- contracts/solidity/GovernanceV2.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index c0768e8a4e..608daf106d 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -175,6 +175,7 @@ contract GovernanceV2 is IGovernanceV2 { require(shareRate < 1000, "invalid rate"); require(!candidateList.contains(msg.sender), "candidate exists"); candidateList.add(msg.sender); + delete exitEpochOf[msg.sender]; uint epoch = _getAndUpdateEpochCount(); // record register time, share rate and balance From 9d2c6a9d0798ac8094094182b1e40021cb818a70 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Thu, 14 Mar 2024 18:32:38 +0800 Subject: [PATCH 37/66] add rewardBase as share rate cache --- contracts/solidity/GovernanceV2.sol | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 608daf106d..750d9df3c7 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -95,6 +95,8 @@ contract GovernanceV2 is IGovernanceV2 { mapping(address => mapping(uint => address)) public votedTo; // voter=>epoch=>amount mapping(address => mapping(uint => uint)) public votedAmount; + // voter=>epoch=>amount + mapping(address => mapping(uint => uint)) public rewardBase; // voter=>epochs mapping(address => uint[]) public unclaimedEpochsOf; @@ -228,6 +230,7 @@ contract GovernanceV2 is IGovernanceV2 { ); } votedAmount[msg.sender][currentEpoch] = voted + msg.value; + rewardBase[msg.sender][currentEpoch] += msg.value * shareRateOf[candidateTo] / 1000; uint received = receivedVotes[candidateTo][currentEpoch]; if (received == 0) { @@ -254,6 +257,7 @@ contract GovernanceV2 is IGovernanceV2 { totalVotes[currentEpoch] -= amount; delete votedTo[msg.sender][currentEpoch]; delete votedAmount[msg.sender][currentEpoch]; + delete rewardBase[msg.sender][currentEpoch]; _safeTransferETH(msg.sender, amount); emit RevokeVote(msg.sender, candidateFrom, amount); @@ -272,9 +276,8 @@ contract GovernanceV2 is IGovernanceV2 { uint epoch = votedIndex[i]; // only epochs before the current running one (the one before current voting) if (epoch < currentEpoch - 1) { - uint epochAmount = votedAmount[msg.sender][epoch]; + totalAmount += votedAmount[msg.sender][epoch]; delete votedAmount[msg.sender][epoch]; - totalAmount += epochAmount; // calculate reward address candidate = votedTo[msg.sender][epoch]; @@ -287,13 +290,12 @@ contract GovernanceV2 is IGovernanceV2 { } if (included) { totalReward += - (epochAmount * - epochRewards[epoch] * - shareRateOf[candidate]) / + (rewardBase[msg.sender][epoch] * + epochRewards[epoch]) / receivedVotes[candidate][epoch] / - CONSENSUS_SIZE / - 1000; + CONSENSUS_SIZE; } + delete rewardBase[msg.sender][epoch]; } else if (epoch >= currentEpoch - 1) { // reconstructed array, the new one always shorter than 2 unclaimedEpochsOf[msg.sender].push(epoch); From bb52dd42abe270be9f2ee1d4f5b8d2a8442495e1 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Fri, 15 Mar 2024 11:16:21 +0800 Subject: [PATCH 38/66] rm unused apis --- contracts/solidity/GovernanceV2.sol | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 750d9df3c7..548e19672b 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -34,16 +34,6 @@ interface IGovernanceV2 { // get the current selected consensus group function getCurrentConsensus() external returns (address[] memory); - - /* - The following should only be used by DBFT module, refer to https://github.com/nspcc-dev/neo-go/blob/master/pkg/core/blockchain.go - */ - - // get the consensus group before the current block is executed, which is the group that should produce this block - function getNextBlockValidators() external returns (address[] memory); - - // select the latest consensus group after the current block is executed, which is the group that should produce the next block - function computeNextBlockValidators() external returns (address[] memory); } interface IGovReward { @@ -340,20 +330,6 @@ contract GovernanceV2 is IGovernanceV2 { return consensusOf[getCurrentRunningEpoch()]; } - function getNextBlockValidators() external view returns (address[] memory) { - uint height = block.number; - if (lastEpochHeight == height) { - // epoch changed in this block, so this is the last block - return consensusOf[getCurrentRunningEpoch() - 1]; - } else { - return consensusOf[getCurrentRunningEpoch()]; - } - } - - function computeNextBlockValidators() external view returns (address[] memory) { - return getCurrentConsensus(); - } - function _computeConsensus( uint epoch ) internal view returns (address[] memory) { From 938fb59101e98d37abd990c0700aa6b1cf44a38b Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Fri, 15 Mar 2024 11:19:36 +0800 Subject: [PATCH 39/66] rename variables --- contracts/solidity/GovernanceV2.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 548e19672b..ebd5bf0e5b 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -58,7 +58,7 @@ contract GovernanceV2 is IGovernanceV2 { uint public epochCount = 1; // the last block height when voting starts - uint public lastEpochHeight = block.number; + uint public currentEpochStartHeight = block.number; // candidate list EnumerableSet.AddressSet internal candidateList; // epoch=>uint @@ -109,7 +109,7 @@ contract GovernanceV2 is IGovernanceV2 { function getCurrentRevokingEpoch() public view returns (uint) { uint epoch = epochCount; if ( - block.number > lastEpochHeight + EPOCH_DURATION && + block.number > currentEpochStartHeight + EPOCH_DURATION && totalVotes[epoch] >= MIN_TOTAL_VOTE && votedCandidates[epoch] >= CONSENSUS_SIZE ) { @@ -130,7 +130,7 @@ contract GovernanceV2 is IGovernanceV2 { function _getAndUpdateEpochCount() internal returns (uint) { uint epoch = epochCount; if ( - block.number > lastEpochHeight + EPOCH_DURATION && + block.number > currentEpochStartHeight + EPOCH_DURATION && totalVotes[epoch] >= MIN_TOTAL_VOTE && votedCandidates[epoch] >= CONSENSUS_SIZE ) { @@ -139,7 +139,7 @@ contract GovernanceV2 is IGovernanceV2 { consensusOf[epoch] = _computeConsensus(epoch); epoch += 1; epochCount = epoch; - lastEpochHeight = block.number; + currentEpochStartHeight = block.number; } return epoch; } From c17b90dbaaf218153baf15c635090dbe6fa4d1b2 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Fri, 15 Mar 2024 12:02:27 +0800 Subject: [PATCH 40/66] update and move settings to genesis file --- contracts/solidity/GovernanceV2.sol | 40 +++++++++++------------------ genesis.json | 29 ++++++++++++--------- 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index ebd5bf0e5b..6d1791bc6d 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -43,22 +43,23 @@ interface IGovReward { contract GovernanceV2 is IGovernanceV2 { using EnumerableSet for EnumerableSet.AddressSet; - uint public constant CONSENSUS_SIZE = 7; + // GovReward contract + address public constant govReward = + 0x1212000000000000000000000000000000000003; + + uint public CONSENSUS_SIZE; // the min balance for voting - uint public constant MIN_VOTE_AMOUNT = 1 ether; + uint public MIN_VOTE_AMOUNT; // register fee - uint public constant REGISTER_FEE = 1000 ether; + uint public REGISTER_FEE; // the min vote amount to change epoch - uint public constant MIN_TOTAL_VOTE = 3000000 ether; + uint public MIN_TOTAL_VOTE; // minimum duration of an epoch (in blocks) - uint public constant EPOCH_DURATION = 120960; - // GovReward contract - address public constant govReward = - 0x1212000000000000000000000000000000000003; + uint public EPOCH_DURATION; - uint public epochCount = 1; + uint public epochCount; // the last block height when voting starts - uint public currentEpochStartHeight = block.number; + uint public currentEpochStartHeight; // candidate list EnumerableSet.AddressSet internal candidateList; // epoch=>uint @@ -90,18 +91,6 @@ contract GovernanceV2 is IGovernanceV2 { // voter=>epochs mapping(address => uint[]) public unclaimedEpochsOf; - constructor() { - consensusOf[0] = [ - address(0x74f4EFFb0B538BAec703346b03B6d9292f53A4CD), - address(0x910AD1641B7125Eff746acCdCa1F11148b22f472), - address(0xfEf5F250aF14DF73f983cAAb7b1F5002189c42E0), - address(0xc51964013acbC6b271FEeCB0feBD9E7A01202930), - address(0xC5bbD9652546BC96bE3DEc97a38eE335f7873Dfa), - address(0x26F1794B81dF2B832545b8B6bbcA196b82E4fEB1), - address(0x0B51369D02e47EE3f143391B837Aa08c31AAA19b) - ]; - } - receive() external payable { epochRewards[getCurrentRunningEpoch()] += msg.value; } @@ -220,7 +209,9 @@ contract GovernanceV2 is IGovernanceV2 { ); } votedAmount[msg.sender][currentEpoch] = voted + msg.value; - rewardBase[msg.sender][currentEpoch] += msg.value * shareRateOf[candidateTo] / 1000; + rewardBase[msg.sender][currentEpoch] += + (msg.value * shareRateOf[candidateTo]) / + 1000; uint received = receivedVotes[candidateTo][currentEpoch]; if (received == 0) { @@ -280,8 +271,7 @@ contract GovernanceV2 is IGovernanceV2 { } if (included) { totalReward += - (rewardBase[msg.sender][epoch] * - epochRewards[epoch]) / + (rewardBase[msg.sender][epoch] * epochRewards[epoch]) / receivedVotes[candidate][epoch] / CONSENSUS_SIZE; } diff --git a/genesis.json b/genesis.json index 0f2cbe7a1e..043d81e45a 100644 --- a/genesis.json +++ b/genesis.json @@ -25,7 +25,7 @@ "0xnode6", "0xnode7" ], - "coinbase": "0x1212100000000000000000000000000000000001" + "coinbase": "0x1212000000000000000000000000000000000003" } }, "difficulty": "1", @@ -34,21 +34,26 @@ "alloc": { "0x1212000000000000000000000000000000000000": { "balance": "0", - "code": "0x6080604052600436106100705760003560e01c806389dc5c841161004e57806389dc5c84146101045780639623609d1461012057806399a88ec414610133578063f3b7dead1461015357600080fd5b8063204e1c7a14610075578063701b70ac146100b25780637eff275e146100e2575b600080fd5b34801561008157600080fd5b506100956100903660046108bd565b610173565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100be57600080fd5b506100d26100cd3660046108bd565b610204565b60405190151581526020016100a9565b3480156100ee57600080fd5b506101026100fd3660046108e1565b6102db565b005b34801561011057600080fd5b50610095600361090960911b0181565b61010261012e366004610961565b61041f565b34801561013f57600080fd5b5061010261014e3660046108e1565b61055b565b34801561015f57600080fd5b5061009561016e3660046108bd565b61061e565b6000806000836001600160a01b031660405161019990635c60da1b60e01b815260040190565b600060405180830381855afa9150503d80600081146101d4576040519150601f19603f3d011682016040523d82523d6000602084013e6101d9565b606091505b5091509150816101e857600080fd5b808060200190518101906101fc9190610a1b565b949350505050565b600080600361090960911b016001600160a01b0316631633da6e6040518163ffffffff1660e01b8152600401600060405180830381865afa15801561024d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526102759190810190610a38565b905060005b81518110156102d15781818151811061029557610295610aea565b60200260200101516001600160a01b0316846001600160a01b0316036102bf575060019392505050565b806102c981610b16565b91505061027a565b5060009392505050565b604080516001600160a01b0380851660208301528316918101919091527f1336f249f9818d347c2448357332e4151be15f64340d7021eac363d7e04f1084906060016040516020818303038152906040528051906020012061033c33610204565b6103615760405162461bcd60e51b815260040161035890610b2f565b60405180910390fd5b61036b8282610644565b61037582826106a2565b15610419576040516308f2839760e41b81526001600160a01b038481166004830152851690638f283970906024015b600060405180830381600087803b1580156103be57600080fd5b505af11580156103d2573d6000803e3d6000fd5b505060408051858152602081018590527ff5aa3d6492eaf1a4d6787c5bd36e8ec61c245d4af2fd1fd387e387a50de9f8c5935001905060405180910390a1610419826107bd565b50505050565b7fe739b9109d83c1c6d0d640fe9ed476fc5862a6de5483b00678a3fffa7a2be2f683838360405160200161045593929190610b98565b6040516020818303038152906040528051906020012061047433610204565b6104905760405162461bcd60e51b815260040161035890610b2f565b61049a8282610644565b6104a482826106a2565b156105545760405163278f794360e11b81526001600160a01b03861690634f1ef2869034906104d99088908890600401610bcd565b6000604051808303818588803b1580156104f257600080fd5b505af1158015610506573d6000803e3d6000fd5b505060408051868152602081018690527ff5aa3d6492eaf1a4d6787c5bd36e8ec61c245d4af2fd1fd387e387a50de9f8c594500191506105439050565b60405180910390a1610554826107bd565b5050505050565b604080516001600160a01b0380851660208301528316918101919091527ef2f7c15cbe06c8d94597cd91fd7f3369eae842359235712def5584f8d270cd90606001604051602081830303815290604052805190602001206105bb33610204565b6105d75760405162461bcd60e51b815260040161035890610b2f565b6105e18282610644565b6105eb82826106a2565b1561041957604051631b2ce7f360e11b81526001600160a01b038481166004830152851690633659cfe6906024016103a4565b6000806000836001600160a01b0316604051610199906303e1469160e61b815260040190565b6000828152602081815260408083203380855290835292819020849055805192835290820184905281018290527f61699483e2a58589628399a22e34da872b583143ab99b3245ba6dacf4974d2e39060600160405180910390a15050565b600080600361090960911b016001600160a01b0316631633da6e6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156106eb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107139190810190610a38565b90506000805b82518110156107975784600080888152602001908152602001600020600085848151811061074957610749610aea565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205403610785578161078181610b16565b9250505b8061078f81610b16565b915050610719565b506003825160026107a89190610bf1565b6107b29190610c08565b109150505b92915050565b6000600361090960911b016001600160a01b0316631633da6e6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610805573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261082d9190810190610a38565b905060005b81518110156108a057600080848152602001908152602001600020600083838151811061086157610861610aea565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060009055808061089890610b16565b915050610832565b505050565b6001600160a01b03811681146108ba57600080fd5b50565b6000602082840312156108cf57600080fd5b81356108da816108a5565b9392505050565b600080604083850312156108f457600080fd5b82356108ff816108a5565b9150602083013561090f816108a5565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156109595761095961091a565b604052919050565b60008060006060848603121561097657600080fd5b8335610981816108a5565b9250602084810135610992816108a5565b9250604085013567ffffffffffffffff808211156109af57600080fd5b818701915087601f8301126109c357600080fd5b8135818111156109d5576109d561091a565b6109e7601f8201601f19168501610930565b915080825288848285010111156109fd57600080fd5b80848401858401376000848284010152508093505050509250925092565b600060208284031215610a2d57600080fd5b81516108da816108a5565b60006020808385031215610a4b57600080fd5b825167ffffffffffffffff80821115610a6357600080fd5b818501915085601f830112610a7757600080fd5b815181811115610a8957610a8961091a565b8060051b9150610a9a848301610930565b8181529183018401918481019088841115610ab457600080fd5b938501935b83851015610ade5784519250610ace836108a5565b8282529385019390850190610ab9565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201610b2857610b28610b00565b5060010190565b6020808252600990820152682737ba1026b4b732b960b91b604082015260600190565b6000815180845260005b81811015610b7857602081850181015186830182015201610b5c565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03848116825283166020820152606060408201819052600090610bc490830184610b52565b95945050505050565b6001600160a01b03831681526040602082018190526000906101fc90830184610b52565b80820281158282048414176107b7576107b7610b00565b600082610c2557634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220ded2ab488883403c3d775d09a6cb9303b9690144976a78d1bd50a51d43b7e4e064736f6c63430008120033" + "code": "0x608060405260043610610212575f3560e01c806370c647d5116101175780639f9d7f811161009f578063cb924df61161006e578063cb924df6146107f1578063ccd668e51461082d578063d8a05cec14610857578063e406fd2a14610881578063ec52fd5c1461089757610246565b80639f9d7f8114610725578063a70b9f0c1461074f578063bad69ad014610779578063c19eb73e146107b557610246565b806379885fd1116100e657806379885fd114610643578063829965cc1461067f57806389dc5c84146106a9578063902bdc26146106d35780639690293b1461070f57610246565b806370c647d51461058957806371785ab9146105c557806374a6b278146105ef578063776892611461061957610246565b806337409c6a1161019a5780634d21e426116101695780634d21e426146104a35780634dc47d34146104df5780635750af771461051b5780636bed4df5146105575780636dd7d8ea1461056d57610246565b806337409c6a146103ff5780633b4866c71461043b578063403b09931461045157806343c14b221461048d57610246565b80630b2a85ea116101e15780630b2a85ea1461030457806319e6e158146103205780631f26f2561461035c578063312ec75c14610386578063347b06d8146103c257610246565b8063038a35381461024a57806306a49fce14610274578063090248641461029e5780630ac1cc20146102da57610246565b36610246573460095f6102236108d3565b81526020019081526020015f205f82825461023e9190612e16565b925050819055005b5f80fd5b348015610255575f80fd5b5061025e6108e8565b60405161026b9190612e58565b60405180910390f35b34801561027f575f80fd5b506102886108ee565b6040516102959190612f58565b60405180910390f35b3480156102a9575f80fd5b506102c460048036038101906102bf9190612fa6565b6108ff565b6040516102d19190612e58565b60405180910390f35b3480156102e5575f80fd5b506102ee610914565b6040516102fb9190612e58565b60405180910390f35b61031e60048036038101906103199190612ffb565b61091a565b005b34801561032b575f80fd5b5061034660048036038101906103419190612ffb565b610ba8565b6040516103539190612e58565b60405180910390f35b348015610367575f80fd5b50610370610bbd565b60405161037d9190612e58565b60405180910390f35b348015610391575f80fd5b506103ac60048036038101906103a79190613026565b610bc3565b6040516103b99190612e58565b60405180910390f35b3480156103cd575f80fd5b506103e860048036038101906103e39190613026565b610bee565b6040516103f6929190613073565b60405180910390f35b34801561040a575f80fd5b5061042560048036038101906104209190613026565b610cb4565b6040516104329190612e58565b60405180910390f35b348015610446575f80fd5b5061044f610d0a565b005b34801561045c575f80fd5b5061047760048036038101906104729190613026565b61125a565b6040516104849190612e58565b60405180910390f35b348015610498575f80fd5b506104a161127a565b005b3480156104ae575f80fd5b506104c960048036038101906104c49190612fa6565b6115e0565b6040516104d69190612e58565b60405180910390f35b3480156104ea575f80fd5b5061050560048036038101906105009190612ffb565b6115f5565b6040516105129190612e58565b60405180910390f35b348015610526575f80fd5b50610541600480360381019061053c9190612ffb565b61160a565b60405161054e9190612e58565b60405180910390f35b348015610562575f80fd5b5061056b61161f565b005b61058760048036038101906105829190612fa6565b6118ff565b005b348015610594575f80fd5b506105af60048036038101906105aa9190612fa6565b611e46565b6040516105bc9190612e58565b60405180910390f35b3480156105d0575f80fd5b506105d9611e5b565b6040516105e69190612e58565b60405180910390f35b3480156105fa575f80fd5b50610603611ed3565b6040516106109190612e58565b60405180910390f35b348015610624575f80fd5b5061062d611ed8565b60405161063a9190612e58565b60405180910390f35b34801561064e575f80fd5b5061066960048036038101906106649190613026565b611ede565b604051610676919061309a565b60405180910390f35b34801561068a575f80fd5b50610693611f1b565b6040516106a09190612e58565b60405180910390f35b3480156106b4575f80fd5b506106bd611f21565b6040516106ca919061309a565b60405180910390f35b3480156106de575f80fd5b506106f960048036038101906106f49190612fa6565b611f39565b6040516107069190612e58565b60405180910390f35b34801561071a575f80fd5b50610723611f4e565b005b348015610730575f80fd5b5061073961208f565b6040516107469190612f58565b60405180910390f35b34801561075a575f80fd5b50610763612130565b6040516107709190612e58565b60405180910390f35b348015610784575f80fd5b5061079f600480360381019061079a9190612fa6565b612136565b6040516107ac9190612e58565b60405180910390f35b3480156107c0575f80fd5b506107db60048036038101906107d691906130b3565b61214b565b6040516107e8919061309a565b60405180910390f35b3480156107fc575f80fd5b5061081760048036038101906108129190613026565b612193565b6040516108249190612e58565b60405180910390f35b348015610838575f80fd5b506108416121b3565b60405161084e9190612e58565b60405180910390f35b348015610862575f80fd5b5061086b6108d3565b6040516108789190612e58565b60405180910390f35b34801561088c575f80fd5b506108956121bc565b005b3480156108a2575f80fd5b506108bd60048036038101906108b89190613026565b6122f6565b6040516108ca9190612e58565b60405180910390f35b5f60016005546108e391906130f1565b905090565b60015481565b60606108fa6007612316565b905090565b600e602052805f5260405f205f915090505481565b60025481565b600254341461095e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109559061317e565b60405180910390fd5b6103e881106109a2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610999906131e6565b60405180910390fd5b6109b633600761233590919063ffffffff16565b156109f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ed9061324e565b60405180910390fd5b610a0a33600761236290919063ffffffff16565b50600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f90555f610a5461238f565b905080600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208190555081600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503460105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208190555060018111610b2a575f610b2c565b805b60115f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507feeda149c76076b34d4b9d8896c2f7efc0d33d1c7b53ea3c5db490d64613f603a33604051610b9c919061309a565b60405180910390a15050565b600a602052805f5260405f205f915090505481565b60065481565b6016602052815f5260405f208181548110610bdc575f80fd5b905f5260205f20015f91509150505481565b5f8060135f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660145f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f2054915091509250929050565b5f60125f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b5f610d1361238f565b90505f805f60165f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20805480602002602001604051908101604052809291908181526020018280548015610d9d57602002820191905f5260205f20905b815481526020019060010190808311610d89575b505050505090505f8151905060165f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f610df19190612d20565b5f5b81811015611202575f838281518110610e0f57610e0e61326c565b5b60200260200101519050600187610e2691906130f1565b81101561117e5760145f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8281526020019081526020015f205486610e859190612e16565b955060145f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8281526020019081526020015f205f90555f60135f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f600c5f8481526020019081526020015f20805480602002602001604051908101604052809291908181526020018280548015610fd457602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610f8b575b505050505090505f805b5f54811015611046578373ffffffffffffffffffffffffffffffffffffffff168382815181106110115761101061326c565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff160361103957600191505b8080600101915050610fde565b508015611127575f5460125f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f205460095f8781526020019081526020015f205460155f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8881526020019081526020015f20546111059190613299565b61110f9190613307565b6111199190613307565b886111249190612e16565b97505b60155f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f90555050506111f4565b60018761118b91906130f1565b81106111f35760165f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081908060018154018082558091505060019003905f5260205f20015f90919091909150555b5b508080600101915050610df3565b506112183384866112139190612e16565b6124ac565b7f703edbfbdca027dbf1185701b17f150b2c280a8f25b570a0a0bab84d72cf347433858560405161124b93929190613337565b60405180910390a15050505050565b6012602052815f5260405f20602052805f5260405f205f91509150505481565b5f611283611e5b565b90505f60135f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f60145f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205490505f8111611386576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137d9061317e565b60405180910390fd5b5f60125f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f20549050818103611406576001600b5f8681526020019081526020015f205f8282546113fe91906130f1565b925050819055505b818161141291906130f1565b60125f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8681526020019081526020015f208190555081600a5f8681526020019081526020015f205f82825461148291906130f1565b9250508190555060135f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560145f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f905560155f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f205f905561159f33836124ac565b7f6ddfb4877cf7f45a590719822a3ae2d41e7a4dc9aeadca0532a85abae1c6ad7f3384846040516115d29392919061336c565b60405180910390a150505050565b6010602052805f5260405f205f915090505481565b6009602052805f5260405f205f915090505481565b600b602052805f5260405f205f915090505481565b5f61162861238f565b90506001811161166d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611664906133eb565b60405180910390fd5b5f8060115f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505b6001836116bd91906130f1565b811015611869575f600c5f8381526020019081526020015f2080548060200260200160405190810160405280929190818152602001828054801561175357602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161170a575b505050505090505f805b5f548110156117c5573373ffffffffffffffffffffffffffffffffffffffff168382815181106117905761178f61326c565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16036117b857600191505b808060010191505061175d565b50801561185a576103e85f54600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e861181c91906130f1565b60095f8781526020019081526020015f20546118389190613299565b6118429190613307565b61184c9190613307565b846118579190612e16565b93505b505080806001019150506116b0565b5060018261187791906130f1565b60115f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055506118c233826124ac565b7fe3ce84385ab3d4dac3d7a146f1f394969d88408c293159506eb6f885a1f6788633826040516118f3929190613073565b60405180910390a15050565b600154341015611944576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193b9061317e565b60405180910390fd5b5f600e5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054116119c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119ba90613453565b60405180910390fd5b5f6119cc61238f565b90505f60145f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205490505f8103611b15578260135f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060165f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2082908060018154018082558091505060019003905f5260205f20015f9091909190915055611bef565b8273ffffffffffffffffffffffffffffffffffffffff1660135f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611bee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be5906134bb565b60405180910390fd5b5b3481611bfb9190612e16565b60145f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f20819055506103e8600d5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205434611c979190613299565b611ca19190613307565b60155f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205f828254611cfb9190612e16565b925050819055505f60125f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f205490505f8103611d82576001600b5f8581526020019081526020015f205f828254611d7a9190612e16565b925050819055505b3481611d8e9190612e16565b60125f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8581526020019081526020015f208190555034600a5f8581526020019081526020015f205f828254611dfe9190612e16565b925050819055507f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc338534604051611e389392919061336c565b60405180910390a150505050565b6011602052805f5260405f205f915090505481565b5f806005549050600454600654611e729190612e16565b43118015611e935750600354600a5f8381526020019081526020015f205410155b8015611eb157505f54600b5f8381526020019081526020015f205410155b15611ecb57600181611ec39190612e16565b915050611ed0565b809150505b90565b5f5481565b60035481565b6013602052815f5260405f20602052805f5260405f205f915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60055481565b73121200000000000000000000000000000000000381565b600d602052805f5260405f205f915090505481565b5f600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205411611fcd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc490613523565b60405180910390fd5b600e5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905561201561238f565b600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507f7c79e6e24ed041d1072d54523b53956f01b91b835f0490856370594d9d14470e33604051612085919061309a565b60405180910390a1565b6060600c5f61209c6108d3565b81526020019081526020015f2080548060200260200160405190810160405280929190818152602001828054801561212657602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116120dd575b5050505050905090565b60045481565b600f602052805f5260405f205f915090505481565b600c602052815f5260405f208181548110612164575f80fd5b905f5260205f20015f915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6015602052815f5260405f20602052805f5260405f205f91509150505481565b5f600554905090565b5f6121c561238f565b90506001600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546122119190612e16565b8111612252576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122499061358b565b60405180910390fd5b6122663360076125a790919063ffffffff16565b505f60105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905060105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f90556122f233826124ac565b5050565b6014602052815f5260405f20602052805f5260405f205f91509150505481565b60605f612324835f016125d4565b905060608190508092505050919050565b5f61235a835f018373ffffffffffffffffffffffffffffffffffffffff165f1b61262d565b905092915050565b5f612387835f018373ffffffffffffffffffffffffffffffffffffffff165f1b61264d565b905092915050565b5f8060055490506004546006546123a69190612e16565b431180156123c75750600354600a5f8381526020019081526020015f205410155b80156123e557505f54600b5f8381526020019081526020015f205410155b156124a55773121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612443575f80fd5b505af1158015612455573d5f803e3d5ffd5b50505050612462816126b4565b600c5f8381526020019081526020015f209080519060200190612486929190612d3e565b506001816124949190612e16565b905080600581905550436006819055505b8091505090565b5f8273ffffffffffffffffffffffffffffffffffffffff16825f67ffffffffffffffff8111156124df576124de6135a9565b5b6040519080825280601f01601f1916602001820160405280156125115781602001600182028036833780820191505090505b5060405161251f9190613642565b5f6040518083038185875af1925050503d805f8114612559576040519150601f19603f3d011682016040523d82523d5f602084013e61255e565b606091505b50509050806125a2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612599906136c8565b60405180910390fd5b505050565b5f6125cc835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612896565b905092915050565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561262157602002820191905f5260205f20905b81548152602001906001019080831161260d575b50505050509050919050565b5f80836001015f8481526020019081526020015f20541415905092915050565b5f612658838361262d565b6126aa57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f2081905550600190506126ae565b5f90505b92915050565b60605f6126bf6108ee565b90505f815190505f8167ffffffffffffffff8111156126e1576126e06135a9565b5b60405190808252806020026020018201604052801561270f5781602001602082028036833780820191505090505b5090505f5b828110156127af5760125f8583815181106127325761273161326c565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8781526020019081526020015f20548282815181106127965761279561326c565b5b6020026020010181815250508080600101915050612714565b506127bc83825f54612992565b5f805467ffffffffffffffff8111156127d8576127d76135a9565b5b6040519080825280602002602001820160405280156128065781602001602082028036833780820191505090505b5090505f5b5f54811015612889578481815181106128275761282661326c565b5b60200260200101518282815181106128425761284161326c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808060010191505061280b565b5080945050505050919050565b5f80836001015f8481526020019081526020015f205490505f8114612987575f6001826128c391906130f1565b90505f6001865f01805490506128d991906130f1565b905080821461293f575f865f0182815481106128f8576128f761326c565b5b905f5260205f200154905080875f0184815481106129195761291861326c565b5b905f5260205f20018190555083876001015f8381526020019081526020015f2081905550505b855f01805480612952576129516136e6565b5b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f90556001935050505061298c565b5f9150505b92915050565b5f835190505f60016002846129a7919061371c565b6129b19190613784565b90505b5f81126129da576129c785858386612ae7565b80806129d2906137c4565b9150506129b4565b505f8290505b81811015612ae057835f815181106129fb576129fa61326c565b5b6020026020010151848281518110612a1657612a1561326c565b5b60200260200101511115612ad357838181518110612a3757612a3661326c565b5b6020026020010151845f81518110612a5257612a5161326c565b5b602002602001018181525050848181518110612a7157612a7061326c565b5b6020026020010151855f81518110612a8c57612a8b61326c565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050612ad285855f86612ae7565b5b80806001019150506129e0565b5050505050565b5f6001836002612af79190613299565b612b019190612e16565b90505b81811015612d195781600182612b1a9190612e16565b108015612b66575083600182612b309190612e16565b81518110612b4157612b4061326c565b5b6020026020010151848281518110612b5c57612b5b61326c565b5b6020026020010151115b15612b7b57600181612b789190612e16565b90505b838381518110612b8e57612b8d61326c565b5b6020026020010151848281518110612ba957612ba861326c565b5b602002602001015111612d1957838381518110612bc957612bc861326c565b5b6020026020010151848281518110612be457612be361326c565b5b6020026020010151858381518110612bff57612bfe61326c565b5b60200260200101868681518110612c1957612c1861326c565b5b6020026020010182815250828152505050848381518110612c3d57612c3c61326c565b5b6020026020010151858281518110612c5857612c5761326c565b5b6020026020010151868381518110612c7357612c7261326c565b5b60200260200101878681518110612c8d57612c8c61326c565b5b602002602001018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681525050508092506001600282612d089190613299565b612d129190612e16565b9050612b04565b5050505050565b5080545f8255905f5260205f2090810190612d3b9190612dc5565b50565b828054828255905f5260205f20908101928215612db4579160200282015b82811115612db3578251825f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190612d5c565b5b509050612dc19190612dc5565b5090565b5b80821115612ddc575f815f905550600101612dc6565b5090565b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612e2082612de0565b9150612e2b83612de0565b9250828201905080821115612e4357612e42612de9565b5b92915050565b612e5281612de0565b82525050565b5f602082019050612e6b5f830184612e49565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f612ec382612e9a565b9050919050565b612ed381612eb9565b82525050565b5f612ee48383612eca565b60208301905092915050565b5f602082019050919050565b5f612f0682612e71565b612f108185612e7b565b9350612f1b83612e8b565b805f5b83811015612f4b578151612f328882612ed9565b9750612f3d83612ef0565b925050600181019050612f1e565b5085935050505092915050565b5f6020820190508181035f830152612f708184612efc565b905092915050565b5f80fd5b612f8581612eb9565b8114612f8f575f80fd5b50565b5f81359050612fa081612f7c565b92915050565b5f60208284031215612fbb57612fba612f78565b5b5f612fc884828501612f92565b91505092915050565b612fda81612de0565b8114612fe4575f80fd5b50565b5f81359050612ff581612fd1565b92915050565b5f602082840312156130105761300f612f78565b5b5f61301d84828501612fe7565b91505092915050565b5f806040838503121561303c5761303b612f78565b5b5f61304985828601612f92565b925050602061305a85828601612fe7565b9150509250929050565b61306d81612eb9565b82525050565b5f6040820190506130865f830185613064565b6130936020830184612e49565b9392505050565b5f6020820190506130ad5f830184613064565b92915050565b5f80604083850312156130c9576130c8612f78565b5b5f6130d685828601612fe7565b92505060206130e785828601612fe7565b9150509250929050565b5f6130fb82612de0565b915061310683612de0565b925082820390508181111561311e5761311d612de9565b5b92915050565b5f82825260208201905092915050565b7f696e73756666696369656e7420616d6f756e74000000000000000000000000005f82015250565b5f613168601383613124565b915061317382613134565b602082019050919050565b5f6020820190508181035f8301526131958161315c565b9050919050565b7f696e76616c6964207261746500000000000000000000000000000000000000005f82015250565b5f6131d0600c83613124565b91506131db8261319c565b602082019050919050565b5f6020820190508181035f8301526131fd816131c4565b9050919050565b7f63616e64696461746520657869737473000000000000000000000000000000005f82015250565b5f613238601083613124565b915061324382613204565b602082019050919050565b5f6020820190508181035f8301526132658161322c565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6132a382612de0565b91506132ae83612de0565b92508282026132bc81612de0565b915082820484148315176132d3576132d2612de9565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61331182612de0565b915061331c83612de0565b92508261332c5761332b6132da565b5b828204905092915050565b5f60608201905061334a5f830186613064565b6133576020830185612e49565b6133646040830184612e49565b949350505050565b5f60608201905061337f5f830186613064565b61338c6020830185613064565b6133996040830184612e49565b949350505050565b7f636c61696d206e6f7420737461727465640000000000000000000000000000005f82015250565b5f6133d5601183613124565b91506133e0826133a1565b602082019050919050565b5f6020820190508181035f830152613402816133c9565b9050919050565b7f63616e646964617465206e6f7420616c6c6f77656400000000000000000000005f82015250565b5f61343d601583613124565b915061344882613409565b602082019050919050565b5f6020820190508181035f83015261346a81613431565b9050919050565b7f6f6e6c79206f6e652063686f69636520697320616c6c6f7765640000000000005f82015250565b5f6134a5601a83613124565b91506134b082613471565b602082019050919050565b5f6020820190508181035f8301526134d281613499565b9050919050565b7f63616e646964617465206e6f74206578697374730000000000000000000000005f82015250565b5f61350d601483613124565b9150613518826134d9565b602082019050919050565b5f6020820190508181035f83015261353a81613501565b9050919050565b7f636c61696d206e6f7420616c6c6f7765640000000000000000000000000000005f82015250565b5f613575601183613124565b915061358082613541565b602082019050919050565b5f6020820190508181035f8301526135a281613569565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f81519050919050565b5f81905092915050565b5f5b838110156136075780820151818401526020810190506135ec565b5f8484015250505050565b5f61361c826135d6565b61362681856135e0565b93506136368185602086016135ea565b80840191505092915050565b5f61364d8284613612565b915081905092915050565b7f736166655472616e736665724554483a20455448207472616e736665722066615f8201527f696c656400000000000000000000000000000000000000000000000000000000602082015250565b5f6136b2602483613124565b91506136bd82613658565b604082019050919050565b5f6020820190508181035f8301526136df816136a6565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f819050919050565b5f61372682613713565b915061373183613713565b925082613741576137406132da565b5b60015f0383147f80000000000000000000000000000000000000000000000000000000000000008314161561377957613778612de9565b5b828205905092915050565b5f61378e82613713565b915061379983613713565b925082820390508181125f8412168282135f8512151617156137be576137bd612de9565b5b92915050565b5f6137ce82613713565b91507f80000000000000000000000000000000000000000000000000000000000000008203613800576137ff612de9565b5b60018203905091905056fea2646970667358221220bc140edffe3d516441820d2e50897d8c7e71254ff08490f53e22023a3e0e990764736f6c63430008180033" }, "0x1212000000000000000000000000000000000001": { "balance": "0", "code": "0x60806040523661001357610011610017565b005b6100115b61001f6101a7565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a576100536101da565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a57610053610231565b63070d7c6960e41b6001600160e01b031982160161009a57610053610277565b621eb96f60e61b6001600160e01b03198216016100b9576100536102a8565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102e8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102fc565b565b606061018e83836040518060600160405280602781526020016108426027913961030c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101e4610384565b60006101f33660048184610695565b81019061020091906106db565b905061021d8160405180602001604052806000815250600061038f565b505060408051602081019091526000815290565b60606000806102433660048184610695565b810190610250919061070c565b915091506102608282600161038f565b604051806020016040528060008152509250505090565b6060610281610384565b60006102903660048184610695565b81019061029d91906106db565b905061021d816103bb565b60606102b2610384565b60006102bc6101a7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102f2610384565b60006102bc610412565b610167610307610412565b610421565b6060600080856001600160a01b03168560405161032991906107f2565b600060405180830381855af49150503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b509150915061037a86838387610445565b9695505050505050565b341561016757600080fd5b610398836104c6565b6000825111806103a55750805b156103b6576103b48383610169565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e46101a7565b604080516001600160a01b03928316815291841660208301520160405180910390a161040f81610506565b50565b600061041c6105af565b905090565b3660008037600080366000845af43d6000803e808015610440573d6000f35b3d6000fd5b606083156104b45782516000036104ad576001600160a01b0385163b6104ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b50816104be565b6104be83836105d7565b949350505050565b6104cf81610601565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03811661056b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101cb565b8151156105e75781518083602001fd5b8060405162461bcd60e51b815260040161014e919061080e565b6001600160a01b0381163b61066e5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61058e565b600080858511156106a557600080fd5b838611156106b257600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d657600080fd5b919050565b6000602082840312156106ed57600080fd5b61018e826106bf565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071f57600080fd5b610728836106bf565b9150602083013567ffffffffffffffff8082111561074557600080fd5b818501915085601f83011261075957600080fd5b81358181111561076b5761076b6106f6565b604051601f8201601f19908116603f01168101908382118183101715610793576107936106f6565b816040528281528860208487010111156107ac57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e95781810151838201526020016107d1565b50506000910152565b600082516108048184602087016107ce565b9190910192915050565b602081526000825180602084015261082d8160408501602087016107ce565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122060cf01d0d0c15c838abecad7eebb680cda1dbe3d5984e7b64b6962b3134b4d8c64736f6c63430008120033", "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x01", - "0x0000000000000000000000000000000000000000000000000000000000000001": "0x01", - "0x000000000000000000000000000000000000000000000000000000000000000b": "0x01", - "0xa15bc60c955c405d20d9149c709e2460f1c2d9a497496a7f46004d1772c3054c": "0x01", - "0xa15bc60c955c405d20d9149c709e2460f1c2d9a497496a7f46004d1772c3054d": "0x02", - "0xd7023ab55818fbdf8325d14db80f1669b44f5ea7af40c6c5612a77bc2207602c": "0x745c8f1af649651f46dcaec2c6eb94068843ae96", - "0xd7023ab55818fbdf8325d14db80f1669b44f5ea7af40c6c5612a77bc2207602d": "0x625eafa3473492007c0dd331e23b1035f6a7fb64", - "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x1212100000000000000000000000000000000001", - "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x1212000000000000000000000000000000000000" + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x07", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0de0b6b3a7640000", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x3635c9adc5dea00000", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x027b46536c66c8e3000000", + "0x0000000000000000000000000000000000000000000000000000000000000004": "0x01d880", + "0x0000000000000000000000000000000000000000000000000000000000000005": "0x01", + "0x13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8": "0x07", + "0x178c34144aa4f22f9dcdc9a6606881972cf65c835163e066ef62f7c270683763": "0x74f4effb0b538baec703346b03b6d9292f53a4cd", + "0x178c34144aa4f22f9dcdc9a6606881972cf65c835163e066ef62f7c270683764": "0x910ad1641b7125eff746accdca1f11148b22f472", + "0x178c34144aa4f22f9dcdc9a6606881972cf65c835163e066ef62f7c270683765": "0xfef5f250af14df73f983caab7b1f5002189c42e0", + "0x178c34144aa4f22f9dcdc9a6606881972cf65c835163e066ef62f7c270683766": "0xc51964013acbc6b271feecb0febd9e7a01202930", + "0x178c34144aa4f22f9dcdc9a6606881972cf65c835163e066ef62f7c270683767": "0xc5bbd9652546bc96be3dec97a38ee335f7873dfa", + "0x178c34144aa4f22f9dcdc9a6606881972cf65c835163e066ef62f7c270683768": "0x26f1794b81df2b832545b8b6bbca196b82e4feb1", + "0x178c34144aa4f22f9dcdc9a6606881972cf65c835163e066ef62f7c270683769": "0x0b51369d02e47ee3f143391b837aa08c31aaa19b" } }, "0x1212000000000000000000000000000000000002": { @@ -62,7 +67,7 @@ }, "0x1212000000000000000000000000000000000003": { "balance": "0", - "code": "0x6080604052600436106100435760003560e01c80631633da6e1461004f57806344004cc11461007a5780635aa6e6751461009c578063f3fef3a3146100d057600080fd5b3661004a57005b600080fd5b34801561005b57600080fd5b506100646100f0565b6040516100719190610400565b60405180910390f35b34801561008657600080fd5b5061009a610095366004610465565b610169565b005b3480156100a857600080fd5b506100b8600161090960911b0181565b6040516001600160a01b039091168152602001610071565b3480156100dc57600080fd5b5061009a6100eb3660046104a6565b6101c6565b6060600161090960911b016001600160a01b031663a3a40ea56040518163ffffffff1660e01b8152600401600060405180830381865afa158015610138573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101609190810190610542565b60200151905090565b33600161090960911b01146101b65760405162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b60448201526064015b60405180910390fd5b6101c182848361021c565b505050565b33600161090960911b011461020e5760405162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b60448201526064016101ad565b6102188282610337565b5050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691610278919061064a565b6000604051808303816000865af19150503d80600081146102b5576040519150601f19603f3d011682016040523d82523d6000602084013e6102ba565b606091505b50915091508180156102e45750805115806102e45750808060200190518101906102e49190610679565b6103305760405162461bcd60e51b815260206004820152601d60248201527f736166655472616e736665723a207472616e73666572206661696c656400000060448201526064016101ad565b5050505050565b604080516000808252602082019092526001600160a01b038416908390604051610361919061064a565b60006040518083038185875af1925050503d806000811461039e576040519150601f19603f3d011682016040523d82523d6000602084013e6103a3565b606091505b50509050806101c15760405162461bcd60e51b8152602060048201526024808201527f736166655472616e736665724554483a20455448207472616e736665722066616044820152631a5b195960e21b60648201526084016101ad565b6020808252825182820181905260009190848201906040850190845b818110156104415783516001600160a01b03168352928401929184019160010161041c565b50909695505050505050565b6001600160a01b038116811461046257600080fd5b50565b60008060006060848603121561047a57600080fd5b83356104858161044d565b925060208401356104958161044d565b929592945050506040919091013590565b600080604083850312156104b957600080fd5b82356104c48161044d565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561050b5761050b6104d2565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561053a5761053a6104d2565b604052919050565b6000602080838503121561055557600080fd5b825167ffffffffffffffff8082111561056d57600080fd5b9084019060a0828703121561058157600080fd5b6105896104e8565b82518152838301518281111561059e57600080fd5b8301601f810188136105af57600080fd5b8051838111156105c1576105c16104d2565b8060051b93506105d2868501610511565b818152938201860193868101908a8611156105ec57600080fd5b928701925b8584101561061657835192506106068361044d565b82825292870192908701906105f1565b8088860152505050506040830151604082015260608301516060820152608083015160808201528094505050505092915050565b6000825160005b8181101561066b5760208186018101518583015201610651565b506000920191825250919050565b60006020828403121561068b57600080fd5b8151801515811461069b57600080fd5b939250505056fea2646970667358221220443685d5efb142dbb193ede991aecc9a71f330539073ee1686ee5024f6adde7364736f6c63430008120033" + "code": "0x608060405260043610610037575f3560e01c80631633da6e146100425780633ccfd60b1461006c5780635aa6e675146100825761003e565b3661003e57005b5f80fd5b34801561004d575f80fd5b506100566100ac565b60405161006391906103d3565b60405180910390f35b348015610077575f80fd5b50610080610137565b005b34801561008d575f80fd5b506100966101d9565b6040516100a39190610402565b60405180910390f35b606073121200000000000000000000000000000000000173ffffffffffffffffffffffffffffffffffffffff16639f9d7f816040518163ffffffff1660e01b81526004015f60405180830381865afa15801561010a573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061013291906105a6565b905090565b73121200000000000000000000000000000000000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101b090610647565b60405180910390fd5b6101d7731212000000000000000000000000000000000001476101f1565b565b73121200000000000000000000000000000000000181565b5f8273ffffffffffffffffffffffffffffffffffffffff16825f67ffffffffffffffff81111561022457610223610440565b5b6040519080825280601f01601f1916602001820160405280156102565781602001600182028036833780820191505090505b5060405161026491906106d1565b5f6040518083038185875af1925050503d805f811461029e576040519150601f19603f3d011682016040523d82523d5f602084013e6102a3565b606091505b50509050806102e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102de90610757565b60405180910390fd5b505050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61033e82610315565b9050919050565b61034e81610334565b82525050565b5f61035f8383610345565b60208301905092915050565b5f602082019050919050565b5f610381826102ec565b61038b81856102f6565b935061039683610306565b805f5b838110156103c65781516103ad8882610354565b97506103b88361036b565b925050600181019050610399565b5085935050505092915050565b5f6020820190508181035f8301526103eb8184610377565b905092915050565b6103fc81610334565b82525050565b5f6020820190506104155f8301846103f3565b92915050565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61047682610430565b810181811067ffffffffffffffff8211171561049557610494610440565b5b80604052505050565b5f6104a761041b565b90506104b3828261046d565b919050565b5f67ffffffffffffffff8211156104d2576104d1610440565b5b602082029050602081019050919050565b5f80fd5b6104f081610334565b81146104fa575f80fd5b50565b5f8151905061050b816104e7565b92915050565b5f61052361051e846104b8565b61049e565b90508083825260208201905060208402830185811115610546576105456104e3565b5b835b8181101561056f578061055b88826104fd565b845260208401935050602081019050610548565b5050509392505050565b5f82601f83011261058d5761058c61042c565b5b815161059d848260208601610511565b91505092915050565b5f602082840312156105bb576105ba610424565b5b5f82015167ffffffffffffffff8111156105d8576105d7610428565b5b6105e484828501610579565b91505092915050565b5f82825260208201905092915050565b7f4e6f7420676f7665726e616e63650000000000000000000000000000000000005f82015250565b5f610631600e836105ed565b915061063c826105fd565b602082019050919050565b5f6020820190508181035f83015261065e81610625565b9050919050565b5f81519050919050565b5f81905092915050565b5f5b8381101561069657808201518184015260208101905061067b565b5f8484015250505050565b5f6106ab82610665565b6106b5818561066f565b93506106c5818560208601610679565b80840191505092915050565b5f6106dc82846106a1565b915081905092915050565b7f736166655472616e736665724554483a20455448207472616e736665722066615f8201527f696c656400000000000000000000000000000000000000000000000000000000602082015250565b5f6107416024836105ed565b915061074c826106e7565b604082019050919050565b5f6020820190508181035f83015261076e81610735565b905091905056fea2646970667358221220a68c92822c68b5b448bc853ee8426363344cf81c780422ede6e9786d4500aec564736f6c63430008180033" }, "0x1212100000000000000000000000000000000001": { "balance": "0", From 46e3f9bfacf6893318122f3a5bcee660328e7487 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 19 Mar 2024 15:25:59 +0800 Subject: [PATCH 41/66] rewrite v2 proposal --- contracts/solidity/GovernanceV2.sol | 397 ++++++++++++---------------- 1 file changed, 169 insertions(+), 228 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 6d1791bc6d..8c1e47d236 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -7,9 +7,10 @@ interface IGovernanceV2 { event Register(address candidate); event Exit(address candidate); event Vote(address voter, address to, uint amount); - event RevokeVote(address voter, address from, uint amount); - event VoterWithdraw(address voter, uint votes, uint reward); - event CandidateClaim(address candidate, uint reward); + event Revoke(address voter, address from, uint amount); + event VoterClaim(address voter, uint reward); + event CandidateWithdraw(address candidate, uint amount); + event Persist(address[] validators); // register to be a candidate with gas function registerCandidate(uint shareRate) external payable; @@ -17,23 +18,30 @@ interface IGovernanceV2 { // exit candidates and wait for withdraw function exitCandidate() external; - // withdraw register fee after 1 epoch - function claimRegisterFee() external; + // withdraw register fee after 2 epoch + function withdrawRegisterFee() external; // vote with gas, only 1 target is allowed function vote(address to) external payable; - // revoke ongoing vote + // revoke votes and claim rewards function revokeVote() external; - // withdraw past vote - function voterWithdraw() external; + // only claim rewards + function claimReward() external; - // claim rewards for being a consensus member - function candidateClaim() external; + /* + The following should only be used by DBFT module, refer to https://github.com/nspcc-dev/neo-go/blob/master/pkg/core/blockchain.go + */ - // get the current selected consensus group - function getCurrentConsensus() external returns (address[] memory); + // get the consensus group before postPersist, which is the group that should produce this block + function getNextBlockValidators() external returns (address[] memory); + + // select the latest consensus group after postPersist, which is the group that should produce the next block + function computeNextBlockValidators() external returns (address[] memory); + + // compute and update cached consensus group + function postPersist() external; } interface IGovReward { @@ -46,105 +54,60 @@ contract GovernanceV2 is IGovernanceV2 { // GovReward contract address public constant govReward = 0x1212000000000000000000000000000000000003; + uint public constant SCALE_FACTOR = 10 ** 18; uint public CONSENSUS_SIZE; // the min balance for voting uint public MIN_VOTE_AMOUNT; // register fee uint public REGISTER_FEE; - // the min vote amount to change epoch - uint public MIN_TOTAL_VOTE; - // minimum duration of an epoch (in blocks) + // duration of an epoch (in blocks) uint public EPOCH_DURATION; - uint public epochCount; - // the last block height when voting starts - uint public currentEpochStartHeight; // candidate list EnumerableSet.AddressSet internal candidateList; - // epoch=>uint - mapping(uint => uint) public epochRewards; - // epoch=>amount - mapping(uint => uint) public totalVotes; - // epoch=>amount - mapping(uint => uint) public votedCandidates; - // epoch=>consensus - mapping(uint => address[]) public consensusOf; // settings about how much reward given to voter mapping(address => uint) public shareRateOf; - // the timestamp when register happens - mapping(address => uint) public registerEpochOf; - // the epoch when exit happens - mapping(address => uint) public exitEpochOf; + // the height when exit happens + mapping(address => uint) public exitHeightOf; // the left register fee to exit mapping(address => uint) public candidateBalanceOf; - // candidate=>epoch - mapping(address => uint) public claimStartEpochOf; - // candidate=>epoch=>amount - mapping(address => mapping(uint => uint)) public receivedVotes; - // voter=>epoch=>candidate - mapping(address => mapping(uint => address)) public votedTo; - // voter=>epoch=>amount - mapping(address => mapping(uint => uint)) public votedAmount; - // voter=>epoch=>amount - mapping(address => mapping(uint => uint)) public rewardBase; - // voter=>epochs - mapping(address => uint[]) public unclaimedEpochsOf; - receive() external payable { - epochRewards[getCurrentRunningEpoch()] += msg.value; - } + // candidate=>amount + mapping(address => uint) public receivedVotes; + // voter=>candidate + mapping(address => address) public votedTo; + // voter=>amount + mapping(address => uint) public votedAmount; - function getCurrentRevokingEpoch() public view returns (uint) { - uint epoch = epochCount; - if ( - block.number > currentEpochStartHeight + EPOCH_DURATION && - totalVotes[epoch] >= MIN_TOTAL_VOTE && - votedCandidates[epoch] >= CONSENSUS_SIZE - ) { - return epoch + 1; - } else { - return epoch; - } - } - - function getCurrentVotingEpoch() public view returns (uint) { - return epochCount; - } - - function getCurrentRunningEpoch() public view returns (uint) { - return epochCount - 1; - } + // the block height when current epoch starts + uint public currentEpochStartHeight; + // the current group of block validators + address[] public currentConsensus; + + // candidate=>total + mapping(address => uint) public candidateGasPerVote; + // voter=>number + mapping(address => uint) public voterGasPerVote; + // voter=>height + mapping(address => uint) public voteHeight; + // candidate=>height=>number + mapping(address => mapping(uint => uint)) public epochStartGasPerVote; - function _getAndUpdateEpochCount() internal returns (uint) { - uint epoch = epochCount; - if ( - block.number > currentEpochStartHeight + EPOCH_DURATION && - totalVotes[epoch] >= MIN_TOTAL_VOTE && - votedCandidates[epoch] >= CONSENSUS_SIZE - ) { - // record gov reward and vote result - IGovReward(govReward).withdraw(); - consensusOf[epoch] = _computeConsensus(epoch); - epoch += 1; - epochCount = epoch; - currentEpochStartHeight = block.number; + receive() external payable { + address[] memory validators = currentConsensus; + uint length = validators.length; + for (uint i = 0; i < length; i++) { + candidateGasPerVote[validators[i]] += + (msg.value * shareRateOf[validators[i]] * SCALE_FACTOR) / + 7 / + 1000 / + receivedVotes[validators[i]]; + _safeTransferETH( + validators[i], + (msg.value * (1000 - shareRateOf[validators[i]])) / 7 / 1000 + ); } - return epoch; - } - - function getVotedByEpoch( - address voter, - uint epoch - ) public view returns (address, uint) { - return (votedTo[voter][epoch], votedAmount[voter][epoch]); - } - - function getReceivedVotesByEpoch( - address candidate, - uint epoch - ) public view returns (uint) { - return receivedVotes[candidate][epoch]; } function getCandidates() public view returns (address[] memory) { @@ -155,180 +118,163 @@ contract GovernanceV2 is IGovernanceV2 { require(msg.value == REGISTER_FEE, "insufficient amount"); require(shareRate < 1000, "invalid rate"); require(!candidateList.contains(msg.sender), "candidate exists"); + require(exitHeightOf[msg.sender] == 0, "left not claimed"); candidateList.add(msg.sender); - delete exitEpochOf[msg.sender]; - uint epoch = _getAndUpdateEpochCount(); - // record register time, share rate and balance - registerEpochOf[msg.sender] = epoch; + // record share rate and balance shareRateOf[msg.sender] = shareRate; candidateBalanceOf[msg.sender] = msg.value; - // set the start point for claim, only if register in epoch 1 can get epoch 0 reward - claimStartEpochOf[msg.sender] = epoch > 1 ? epoch : 0; emit Register(msg.sender); } function exitCandidate() external { - require(registerEpochOf[msg.sender] > 0, "candidate not exists"); - // delete register time, cannot be voted - delete registerEpochOf[msg.sender]; - // record exit time, but candidate list not removed, balance still locked - exitEpochOf[msg.sender] = _getAndUpdateEpochCount(); + require(candidateList.contains(msg.sender), "candidate not exists"); + // remove candidate list, balance still locked + candidateList.remove(msg.sender); + exitHeightOf[msg.sender] = block.number; emit Exit(msg.sender); } - function claimRegisterFee() external { - // require 2 epochs to exit candidate list, so that the last round of vote can work as expected - uint epoch = _getAndUpdateEpochCount(); - require(epoch > exitEpochOf[msg.sender] + 1, "claim not allowed"); - - // reorg candidate list - candidateList.remove(msg.sender); + function withdrawRegisterFee() external { + // require 2 epochs to exit candidate list + // NOTE: suppose postPersist always happens in time + require( + exitHeightOf[msg.sender] > 0 && + block.number > exitHeightOf[msg.sender] + 2 * EPOCH_DURATION, + "withdraw not allowed" + ); // send back balance uint amount = candidateBalanceOf[msg.sender]; delete candidateBalanceOf[msg.sender]; + delete exitHeightOf[msg.sender]; _safeTransferETH(msg.sender, amount); + emit CandidateWithdraw(msg.sender, amount); } function vote(address candidateTo) external payable { require(msg.value >= MIN_VOTE_AMOUNT, "insufficient amount"); - require(registerEpochOf[candidateTo] > 0, "candidate not allowed"); - // the first person vote in new epoch will pay for update - uint currentEpoch = _getAndUpdateEpochCount(); - - uint voted = votedAmount[msg.sender][currentEpoch]; - // add this epoch to personal record if never voted - if (voted == 0) { - votedTo[msg.sender][currentEpoch] = candidateTo; - unclaimedEpochsOf[msg.sender].push(currentEpoch); + require(candidateList.contains(candidateTo), "candidate not allowed"); + address votedCandidate = votedTo[msg.sender]; + require( + votedCandidate == candidateTo || votedCandidate == address(0), + "only one choice is allowed" + ); + + // settle reward here + if (votedCandidate != address(0)) { + _settleReward(msg.sender, votedCandidate); } else { - require( - votedTo[msg.sender][currentEpoch] == candidateTo, - "only one choice is allowed" - ); - } - votedAmount[msg.sender][currentEpoch] = voted + msg.value; - rewardBase[msg.sender][currentEpoch] += - (msg.value * shareRateOf[candidateTo]) / - 1000; - - uint received = receivedVotes[candidateTo][currentEpoch]; - if (received == 0) { - votedCandidates[currentEpoch] += 1; + // record tag value + votedTo[msg.sender] = candidateTo; + voterGasPerVote[msg.sender] = candidateGasPerVote[candidateTo]; } - receivedVotes[candidateTo][currentEpoch] = received + msg.value; - totalVotes[currentEpoch] += msg.value; + + // update votes + votedAmount[msg.sender] += msg.value; + receivedVotes[candidateTo] += msg.value; + // NOTE: the left reward in current epoch will be unclaimable + voteHeight[msg.sender] = block.number; emit Vote(msg.sender, candidateTo, msg.value); } function revokeVote() external { - // revoke will not trigger epoch change - uint currentEpoch = getCurrentRevokingEpoch(); - address candidateFrom = votedTo[msg.sender][currentEpoch]; - uint amount = votedAmount[msg.sender][currentEpoch]; - require(amount > 0, "insufficient amount"); - - uint received = receivedVotes[candidateFrom][currentEpoch]; - if (received == amount) { - votedCandidates[currentEpoch] -= 1; - } - receivedVotes[candidateFrom][currentEpoch] = received - amount; - totalVotes[currentEpoch] -= amount; - delete votedTo[msg.sender][currentEpoch]; - delete votedAmount[msg.sender][currentEpoch]; - delete rewardBase[msg.sender][currentEpoch]; + address candidateFrom = votedTo[msg.sender]; + uint amount = votedAmount[msg.sender]; + require( + candidateFrom != address(0) && amount > 0, + "revoke not allowed" + ); + + // settle reward here + _settleReward(msg.sender, candidateFrom); + + // update votes + receivedVotes[candidateFrom] -= amount; + delete votedTo[msg.sender]; + delete votedAmount[msg.sender]; + + // delete tag value + delete voterGasPerVote[msg.sender]; + delete voteHeight[msg.sender]; + _safeTransferETH(msg.sender, amount); + emit Revoke(msg.sender, candidateFrom, amount); + } - emit RevokeVote(msg.sender, candidateFrom, amount); + function claimReward() external { + address votedCandidate = votedTo[msg.sender]; + require(votedCandidate != address(0), "claim not allowed"); + _settleReward(msg.sender, votedCandidate); } - function voterWithdraw() external { - // use epochCount, to lock votes and rewards until epoch change - uint currentEpoch = _getAndUpdateEpochCount(); - uint totalAmount = 0; - uint totalReward = 0; - // loop all voted epochs - uint[] memory votedIndex = unclaimedEpochsOf[msg.sender]; - uint indexLength = votedIndex.length; - delete unclaimedEpochsOf[msg.sender]; - for (uint i = 0; i < indexLength; i++) { - uint epoch = votedIndex[i]; - // only epochs before the current running one (the one before current voting) - if (epoch < currentEpoch - 1) { - totalAmount += votedAmount[msg.sender][epoch]; - delete votedAmount[msg.sender][epoch]; - - // calculate reward - address candidate = votedTo[msg.sender][epoch]; - address[] memory consensus = consensusOf[epoch]; - bool included = false; - for (uint j = 0; j < CONSENSUS_SIZE; j++) { - if (consensus[j] == candidate) { - included = true; - } - } - if (included) { - totalReward += - (rewardBase[msg.sender][epoch] * epochRewards[epoch]) / - receivedVotes[candidate][epoch] / - CONSENSUS_SIZE; - } - delete rewardBase[msg.sender][epoch]; - } else if (epoch >= currentEpoch - 1) { - // reconstructed array, the new one always shorter than 2 - unclaimedEpochsOf[msg.sender].push(epoch); - } + function postPersist() external { + // NOTE: suppose postPersist always happens when equal + require( + block.number >= currentEpochStartHeight + EPOCH_DURATION, + "persist not allowed" + ); + IGovReward(govReward).withdraw(); + + currentEpochStartHeight = block.number; + currentConsensus = _computeConsensus(); + uint length = currentConsensus.length; + for (uint i = 0; i < length; i++) { + epochStartGasPerVote[currentConsensus[i]][ + currentEpochStartHeight / EPOCH_DURATION + ] = candidateGasPerVote[currentConsensus[i]]; } - _safeTransferETH(msg.sender, totalAmount + totalReward); - emit VoterWithdraw(msg.sender, totalAmount, totalReward); + emit Persist(currentConsensus); } - function candidateClaim() external { - // use epochCount, to lock rewards until epoch change - uint currentEpoch = _getAndUpdateEpochCount(); - require(currentEpoch > 1, "claim not started"); - uint totalReward = 0; - // loop all unclaimed epochs - for ( - uint i = claimStartEpochOf[msg.sender]; - i < currentEpoch - 1; - i++ - ) { - // only epochs before the current running one (the one before current voting) - address[] memory consensus = consensusOf[i]; - bool included = false; - for (uint j = 0; j < CONSENSUS_SIZE; j++) { - if (consensus[j] == msg.sender) { - included = true; - } - } - if (included) { - totalReward += - (epochRewards[i] * (1000 - shareRateOf[msg.sender])) / - CONSENSUS_SIZE / - 1000; - } + function getNextBlockValidators() external view returns (address[] memory) { + return currentConsensus; + } + + function computeNextBlockValidators() + external + view + returns (address[] memory) + { + return _computeConsensus(); + } + + function _settleReward(address voter, address candidate) internal { + IGovReward(govReward).withdraw(); + + uint height = voteHeight[voter]; + uint lastGasPerVote = voterGasPerVote[voter]; + uint latestGasPerVote = candidateGasPerVote[candidate]; + + // NOTE: suppose postPersist always happens in the correct block at expected height + // NOTE: suppose postPersist always happens at the beginning of a block, then vote in that block should wait another epoch to farm reward + uint voteEpochEndGasPerVote = epochStartGasPerVote[candidate][ + (height - 1) / EPOCH_DURATION + 1 + ]; + if (voteEpochEndGasPerVote > lastGasPerVote) { + lastGasPerVote = voteEpochEndGasPerVote; } - claimStartEpochOf[msg.sender] = currentEpoch - 1; - _safeTransferETH(msg.sender, totalReward); - emit CandidateClaim(msg.sender, totalReward); + + uint reward = (votedAmount[voter] * + (latestGasPerVote - lastGasPerVote)) / SCALE_FACTOR; + voterGasPerVote[voter] = latestGasPerVote; + _safeTransferETH(voter, reward); + emit VoterClaim(voter, reward); } - function getCurrentConsensus() public view returns (address[] memory) { - return consensusOf[getCurrentRunningEpoch()]; + function _safeTransferETH(address to, uint value) internal { + (bool success, ) = to.call{value: value}(new bytes(0)); + require(success, "safeTransferETH: ETH transfer failed"); } - function _computeConsensus( - uint epoch - ) internal view returns (address[] memory) { + function _computeConsensus() internal view returns (address[] memory) { // build up a votes array address[] memory candidates = getCandidates(); uint length = candidates.length; uint[] memory votes = new uint[](length); for (uint i = 0; i < length; i++) { - votes[i] = receivedVotes[candidates[i]][epoch]; + votes[i] = receivedVotes[candidates[i]]; } // sort top CONSENSUS_SIZE based on votes @@ -342,11 +288,6 @@ contract GovernanceV2 is IGovernanceV2 { return consensus; } - function _safeTransferETH(address to, uint value) internal { - (bool success, ) = to.call{value: value}(new bytes(0)); - require(success, "safeTransferETH: ETH transfer failed"); - } - function _topK( address[] memory candidates, uint[] memory votes, From e2e4ccc18bc8aa1836272521e68c03e220faa684 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 19 Mar 2024 15:31:40 +0800 Subject: [PATCH 42/66] fix register value check --- contracts/solidity/GovernanceV2.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 8c1e47d236..89c637617f 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -115,7 +115,7 @@ contract GovernanceV2 is IGovernanceV2 { } function registerCandidate(uint shareRate) external payable { - require(msg.value == REGISTER_FEE, "insufficient amount"); + require(msg.value >= REGISTER_FEE, "insufficient amount"); require(shareRate < 1000, "invalid rate"); require(!candidateList.contains(msg.sender), "candidate exists"); require(exitHeightOf[msg.sender] == 0, "left not claimed"); From 1ddc572a01f35204fd814c652fe8b3cb87a923b6 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 19 Mar 2024 16:05:49 +0800 Subject: [PATCH 43/66] fix distribution --- contracts/solidity/GovernanceV2.sol | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 89c637617f..f5aeecf042 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -100,12 +100,14 @@ contract GovernanceV2 is IGovernanceV2 { for (uint i = 0; i < length; i++) { candidateGasPerVote[validators[i]] += (msg.value * shareRateOf[validators[i]] * SCALE_FACTOR) / - 7 / + CONSENSUS_SIZE / 1000 / receivedVotes[validators[i]]; _safeTransferETH( validators[i], - (msg.value * (1000 - shareRateOf[validators[i]])) / 7 / 1000 + (msg.value * (1000 - shareRateOf[validators[i]])) / + CONSENSUS_SIZE / + 1000 ); } } From bfff1d93a468abf780ddfb21854ceb96e05b1cda Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 19 Mar 2024 16:49:22 +0800 Subject: [PATCH 44/66] bugfix --- contracts/solidity/GovernanceV2.sol | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index f5aeecf042..4e093e0e6b 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -30,6 +30,9 @@ interface IGovernanceV2 { // only claim rewards function claimReward() external; + // get consensus group members + function getCurrentConsensus() external view returns (address[] memory); + /* The following should only be used by DBFT module, refer to https://github.com/nspcc-dev/neo-go/blob/master/pkg/core/blockchain.go */ @@ -217,23 +220,31 @@ contract GovernanceV2 is IGovernanceV2 { block.number >= currentEpochStartHeight + EPOCH_DURATION, "persist not allowed" ); - IGovReward(govReward).withdraw(); - currentEpochStartHeight = block.number; - currentConsensus = _computeConsensus(); - uint length = currentConsensus.length; + // update tag values + address[] memory consensus = currentConsensus; + uint length = consensus.length; for (uint i = 0; i < length; i++) { - epochStartGasPerVote[currentConsensus[i]][ + epochStartGasPerVote[consensus[i]][ currentEpochStartHeight / EPOCH_DURATION - ] = candidateGasPerVote[currentConsensus[i]]; + ] = candidateGasPerVote[consensus[i]]; } + IGovReward(govReward).withdraw(); + + // compute and update consensus + currentEpochStartHeight = block.number; + currentConsensus = _computeConsensus(); emit Persist(currentConsensus); } - function getNextBlockValidators() external view returns (address[] memory) { + function getCurrentConsensus() external view returns (address[] memory) { return currentConsensus; } + function getNextBlockValidators() external view returns (address[] memory) { + return getCurrentConsensus(); + } + function computeNextBlockValidators() external view From 0e7b35c7534b089c9f1d000390d9c2725d39f9dd Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 19 Mar 2024 16:51:02 +0800 Subject: [PATCH 45/66] fix modifier --- contracts/solidity/GovernanceV2.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 4e093e0e6b..c6f0cc4b7c 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -237,7 +237,7 @@ contract GovernanceV2 is IGovernanceV2 { emit Persist(currentConsensus); } - function getCurrentConsensus() external view returns (address[] memory) { + function getCurrentConsensus() public view returns (address[] memory) { return currentConsensus; } From 694a23285593c0925f2621760684621d2c646f80 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Tue, 19 Mar 2024 18:45:24 +0800 Subject: [PATCH 46/66] fix postPersist --- contracts/solidity/GovernanceV2.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index c6f0cc4b7c..f8c91a8611 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -222,6 +222,7 @@ contract GovernanceV2 is IGovernanceV2 { ); // update tag values + IGovReward(govReward).withdraw(); address[] memory consensus = currentConsensus; uint length = consensus.length; for (uint i = 0; i < length; i++) { @@ -229,7 +230,6 @@ contract GovernanceV2 is IGovernanceV2 { currentEpochStartHeight / EPOCH_DURATION ] = candidateGasPerVote[consensus[i]]; } - IGovReward(govReward).withdraw(); // compute and update consensus currentEpochStartHeight = block.number; From cee0cd83478a0c83ac94cbe436a65edb1a5812bd Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Wed, 20 Mar 2024 11:59:26 +0800 Subject: [PATCH 47/66] update variable naming --- contracts/solidity/GovernanceV2.sol | 40 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index f8c91a8611..5267b198cc 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -57,15 +57,15 @@ contract GovernanceV2 is IGovernanceV2 { // GovReward contract address public constant govReward = 0x1212000000000000000000000000000000000003; - uint public constant SCALE_FACTOR = 10 ** 18; + uint public constant scaleFactor = 10 ** 18; - uint public CONSENSUS_SIZE; + uint public consensusSize; // the min balance for voting - uint public MIN_VOTE_AMOUNT; + uint public minVoteAmount; // register fee - uint public REGISTER_FEE; + uint public registerFee; // duration of an epoch (in blocks) - uint public EPOCH_DURATION; + uint public epochDuration; // candidate list EnumerableSet.AddressSet internal candidateList; @@ -102,14 +102,14 @@ contract GovernanceV2 is IGovernanceV2 { uint length = validators.length; for (uint i = 0; i < length; i++) { candidateGasPerVote[validators[i]] += - (msg.value * shareRateOf[validators[i]] * SCALE_FACTOR) / - CONSENSUS_SIZE / + (msg.value * shareRateOf[validators[i]] * scaleFactor) / + consensusSize / 1000 / receivedVotes[validators[i]]; _safeTransferETH( validators[i], (msg.value * (1000 - shareRateOf[validators[i]])) / - CONSENSUS_SIZE / + consensusSize / 1000 ); } @@ -120,7 +120,7 @@ contract GovernanceV2 is IGovernanceV2 { } function registerCandidate(uint shareRate) external payable { - require(msg.value >= REGISTER_FEE, "insufficient amount"); + require(msg.value >= registerFee, "insufficient amount"); require(shareRate < 1000, "invalid rate"); require(!candidateList.contains(msg.sender), "candidate exists"); require(exitHeightOf[msg.sender] == 0, "left not claimed"); @@ -145,7 +145,7 @@ contract GovernanceV2 is IGovernanceV2 { // NOTE: suppose postPersist always happens in time require( exitHeightOf[msg.sender] > 0 && - block.number > exitHeightOf[msg.sender] + 2 * EPOCH_DURATION, + block.number > exitHeightOf[msg.sender] + 2 * epochDuration, "withdraw not allowed" ); @@ -158,7 +158,7 @@ contract GovernanceV2 is IGovernanceV2 { } function vote(address candidateTo) external payable { - require(msg.value >= MIN_VOTE_AMOUNT, "insufficient amount"); + require(msg.value >= minVoteAmount, "insufficient amount"); require(candidateList.contains(candidateTo), "candidate not allowed"); address votedCandidate = votedTo[msg.sender]; require( @@ -217,7 +217,7 @@ contract GovernanceV2 is IGovernanceV2 { function postPersist() external { // NOTE: suppose postPersist always happens when equal require( - block.number >= currentEpochStartHeight + EPOCH_DURATION, + block.number >= currentEpochStartHeight + epochDuration, "persist not allowed" ); @@ -227,7 +227,7 @@ contract GovernanceV2 is IGovernanceV2 { uint length = consensus.length; for (uint i = 0; i < length; i++) { epochStartGasPerVote[consensus[i]][ - currentEpochStartHeight / EPOCH_DURATION + currentEpochStartHeight / epochDuration ] = candidateGasPerVote[consensus[i]]; } @@ -263,14 +263,14 @@ contract GovernanceV2 is IGovernanceV2 { // NOTE: suppose postPersist always happens in the correct block at expected height // NOTE: suppose postPersist always happens at the beginning of a block, then vote in that block should wait another epoch to farm reward uint voteEpochEndGasPerVote = epochStartGasPerVote[candidate][ - (height - 1) / EPOCH_DURATION + 1 + (height - 1) / epochDuration + 1 ]; if (voteEpochEndGasPerVote > lastGasPerVote) { lastGasPerVote = voteEpochEndGasPerVote; } uint reward = (votedAmount[voter] * - (latestGasPerVote - lastGasPerVote)) / SCALE_FACTOR; + (latestGasPerVote - lastGasPerVote)) / scaleFactor; voterGasPerVote[voter] = latestGasPerVote; _safeTransferETH(voter, reward); emit VoterClaim(voter, reward); @@ -290,12 +290,12 @@ contract GovernanceV2 is IGovernanceV2 { votes[i] = receivedVotes[candidates[i]]; } - // sort top CONSENSUS_SIZE based on votes - _topK(candidates, votes, CONSENSUS_SIZE); + // sort top consensusSize based on votes + _topK(candidates, votes, consensusSize); - // return the first CONSENSUS_SIZE candidates as consensus list - address[] memory consensus = new address[](CONSENSUS_SIZE); - for (uint i = 0; i < CONSENSUS_SIZE; i++) { + // return the first consensusSize candidates as consensus list + address[] memory consensus = new address[](consensusSize); + for (uint i = 0; i < consensusSize; i++) { consensus[i] = candidates[i]; } return consensus; From 5f746f3e38ce3a89678ede60687ca5d5350ba99a Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Fri, 22 Mar 2024 10:26:47 +0800 Subject: [PATCH 48/66] prevent postPersist from failure --- contracts/solidity/GovernanceV2.sol | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 5267b198cc..cac742afb9 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -215,11 +215,9 @@ contract GovernanceV2 is IGovernanceV2 { } function postPersist() external { - // NOTE: suppose postPersist always happens when equal - require( - block.number >= currentEpochStartHeight + epochDuration, - "persist not allowed" - ); + if (block.number < currentEpochStartHeight + epochDuration) { + return; + } // update tag values IGovReward(govReward).withdraw(); From c556295626b1f7296e67240d187195910d57a569 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Fri, 22 Mar 2024 11:17:12 +0800 Subject: [PATCH 49/66] rename postPersist to onPersist --- contracts/solidity/GovernanceV2.sol | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index cac742afb9..b297bb7818 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -37,14 +37,14 @@ interface IGovernanceV2 { The following should only be used by DBFT module, refer to https://github.com/nspcc-dev/neo-go/blob/master/pkg/core/blockchain.go */ - // get the consensus group before postPersist, which is the group that should produce this block + // get the consensus group before onPersist, which is the group that should produce this block function getNextBlockValidators() external returns (address[] memory); - // select the latest consensus group after postPersist, which is the group that should produce the next block + // select the latest consensus group after onPersist, which is the group that should produce the next block function computeNextBlockValidators() external returns (address[] memory); // compute and update cached consensus group - function postPersist() external; + function onPersist() external; } interface IGovReward { @@ -142,7 +142,7 @@ contract GovernanceV2 is IGovernanceV2 { function withdrawRegisterFee() external { // require 2 epochs to exit candidate list - // NOTE: suppose postPersist always happens in time + // NOTE: suppose onPersist always happens in time require( exitHeightOf[msg.sender] > 0 && block.number > exitHeightOf[msg.sender] + 2 * epochDuration, @@ -214,7 +214,7 @@ contract GovernanceV2 is IGovernanceV2 { _settleReward(msg.sender, votedCandidate); } - function postPersist() external { + function onPersist() external { if (block.number < currentEpochStartHeight + epochDuration) { return; } @@ -258,8 +258,8 @@ contract GovernanceV2 is IGovernanceV2 { uint lastGasPerVote = voterGasPerVote[voter]; uint latestGasPerVote = candidateGasPerVote[candidate]; - // NOTE: suppose postPersist always happens in the correct block at expected height - // NOTE: suppose postPersist always happens at the beginning of a block, then vote in that block should wait another epoch to farm reward + // NOTE: suppose onPersist always happens in the correct block at expected height + // NOTE: suppose onPersist always happens at the beginning of a block, then vote in that block should wait another epoch to farm reward uint voteEpochEndGasPerVote = epochStartGasPerVote[candidate][ (height - 1) / epochDuration + 1 ]; From d5e6673e27dd9aa196326b2c4d911d63cbfc63b0 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Fri, 22 Mar 2024 11:28:57 +0800 Subject: [PATCH 50/66] add side call check in onPersist --- contracts/solidity/GovernanceV2.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index b297bb7818..4719336bd6 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -215,6 +215,7 @@ contract GovernanceV2 is IGovernanceV2 { } function onPersist() external { + require(msg.sender == address(0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE), "side call not allowed"); if (block.number < currentEpochStartHeight + epochDuration) { return; } From 7018c0976e50e552c065f94d073ca47b62d2481a Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Fri, 22 Mar 2024 11:32:37 +0800 Subject: [PATCH 51/66] remove unused methods --- contracts/solidity/GovernanceV2.sol | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 4719336bd6..266736df6b 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -33,16 +33,6 @@ interface IGovernanceV2 { // get consensus group members function getCurrentConsensus() external view returns (address[] memory); - /* - The following should only be used by DBFT module, refer to https://github.com/nspcc-dev/neo-go/blob/master/pkg/core/blockchain.go - */ - - // get the consensus group before onPersist, which is the group that should produce this block - function getNextBlockValidators() external returns (address[] memory); - - // select the latest consensus group after onPersist, which is the group that should produce the next block - function computeNextBlockValidators() external returns (address[] memory); - // compute and update cached consensus group function onPersist() external; } @@ -240,18 +230,6 @@ contract GovernanceV2 is IGovernanceV2 { return currentConsensus; } - function getNextBlockValidators() external view returns (address[] memory) { - return getCurrentConsensus(); - } - - function computeNextBlockValidators() - external - view - returns (address[] memory) - { - return _computeConsensus(); - } - function _settleReward(address voter, address candidate) internal { IGovReward(govReward).withdraw(); From 786e78b4a45fd2f0b90114c1b549bcc8a82fb6ed Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Fri, 22 Mar 2024 18:00:37 +0800 Subject: [PATCH 52/66] fix onPersist --- contracts/solidity/GovernanceV2.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 266736df6b..ecd3cf81bd 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -212,12 +212,12 @@ contract GovernanceV2 is IGovernanceV2 { // update tag values IGovReward(govReward).withdraw(); - address[] memory consensus = currentConsensus; - uint length = consensus.length; + address[] memory candidates = candidateList.values(); + uint length = candidates.length; for (uint i = 0; i < length; i++) { - epochStartGasPerVote[consensus[i]][ + epochStartGasPerVote[candidates[i]][ currentEpochStartHeight / epochDuration - ] = candidateGasPerVote[consensus[i]]; + ] = candidateGasPerVote[candidates[i]]; } // compute and update consensus From ed14630d21569ed643e20a4208c71ff0c32494b4 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Fri, 22 Mar 2024 22:09:11 +0800 Subject: [PATCH 53/66] update genesis file for testing --- genesis.json | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/genesis.json b/genesis.json index 043d81e45a..b434fc63f7 100644 --- a/genesis.json +++ b/genesis.json @@ -43,17 +43,15 @@ "0x0000000000000000000000000000000000000000000000000000000000000000": "0x07", "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0de0b6b3a7640000", "0x0000000000000000000000000000000000000000000000000000000000000002": "0x3635c9adc5dea00000", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x027b46536c66c8e3000000", - "0x0000000000000000000000000000000000000000000000000000000000000004": "0x01d880", - "0x0000000000000000000000000000000000000000000000000000000000000005": "0x01", - "0x13649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8": "0x07", - "0x178c34144aa4f22f9dcdc9a6606881972cf65c835163e066ef62f7c270683763": "0x74f4effb0b538baec703346b03b6d9292f53a4cd", - "0x178c34144aa4f22f9dcdc9a6606881972cf65c835163e066ef62f7c270683764": "0x910ad1641b7125eff746accdca1f11148b22f472", - "0x178c34144aa4f22f9dcdc9a6606881972cf65c835163e066ef62f7c270683765": "0xfef5f250af14df73f983caab7b1f5002189c42e0", - "0x178c34144aa4f22f9dcdc9a6606881972cf65c835163e066ef62f7c270683766": "0xc51964013acbc6b271feecb0febd9e7a01202930", - "0x178c34144aa4f22f9dcdc9a6606881972cf65c835163e066ef62f7c270683767": "0xc5bbd9652546bc96be3dec97a38ee335f7873dfa", - "0x178c34144aa4f22f9dcdc9a6606881972cf65c835163e066ef62f7c270683768": "0x26f1794b81df2b832545b8b6bbca196b82e4feb1", - "0x178c34144aa4f22f9dcdc9a6606881972cf65c835163e066ef62f7c270683769": "0x0b51369d02e47ee3f143391b837aa08c31aaa19b" + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x01d880", + "0x000000000000000000000000000000000000000000000000000000000000000d": "0x07", + "0xd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb5": "0x74f4effb0b538baec703346b03b6d9292f53a4cd", + "0xd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb6": "0x910ad1641b7125eff746accdca1f11148b22f472", + "0xd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb7": "0xfef5f250af14df73f983caab7b1f5002189c42e0", + "0xd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb8": "0xc51964013acbc6b271feecb0febd9e7a01202930", + "0xd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb9": "0xc5bbd9652546bc96be3dec97a38ee335f7873dfa", + "0xd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eba": "0x26f1794b81df2b832545b8b6bbca196b82e4feb1", + "0xd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1ebb": "0x0b51369d02e47ee3f143391b837aa08c31aaa19b" } }, "0x1212000000000000000000000000000000000002": { @@ -71,7 +69,7 @@ }, "0x1212100000000000000000000000000000000001": { "balance": "0", - "code": "0x6080604052600436106100f75760003560e01c806389dc5c841161008a578063b384abef11610059578063b384abef1461029d578063c885bc58146102b0578063ecd88a86146102c5578063f73a8b4a146102db57600080fd5b806389dc5c8414610205578063958d686e1461023957806395a772ff14610266578063a3a40ea51461028857600080fd5b8063701b70ac116100c6578063701b70ac1461018a57806375ea3a6d146101ba5780637765f548146101d05780637bb71bcf146101ef57600080fd5b8063038a35381461010357806310de6573146101325780633980663d1461014857806344a040f51461016a57600080fd5b366100fe57005b600080fd5b34801561010f57600080fd5b5061011f670de0b6b3a764000081565b6040519081526020015b60405180910390f35b34801561013e57600080fd5b5061011f60005481565b34801561015457600080fd5b5061015d6102fb565b604051610129919061146a565b34801561017657600080fd5b5061011f610185366004611505565b610473565b34801561019657600080fd5b506101aa6101a5366004611505565b61076d565b6040519015158152602001610129565b3480156101c657600080fd5b5061011f60025481565b3480156101dc57600080fd5b5061011f6a027b46536c66c8e300000081565b3480156101fb57600080fd5b5061011f600a5481565b34801561021157600080fd5b50610221600361090960911b0181565b6040516001600160a01b039091168152602001610129565b34801561024557600080fd5b50610259610254366004611527565b6107e6565b6040516101299190611540565b34801561027257600080fd5b506102866102813660046115a6565b61098e565b005b34801561029457600080fd5b50610259610c3b565b6102866102ab366004611677565b610c7b565b3480156102bc57600080fd5b50610286611087565b3480156102d157600080fd5b5061011f60015481565b3480156102e757600080fd5b506102866102f6366004611527565b611166565b60606000600154600254600161031191906116af565b61031b91906116c8565b905060008167ffffffffffffffff81111561033857610338611590565b60405190808252806020026020018201604052801561038d57816020015b61037a60405180606001604052806000815260200160008152602001606081525090565b8152602001906001900390816103565790505b50905060005b8281101561046c5760046000826001546103ad91906116af565b815260200190815260200160002060405180606001604052908160008201548152602001600182015481526020016002820180548060200260200160405190810160405280929190818152602001828054801561043357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610415575b50505050508152505082828151811061044e5761044e6116db565b60200260200101819052508080610464906116f1565b915050610393565b5092915050565b600080548152600360209081526040808320815160a081018352815481526001820180548451818702810187019095528085528695929485840193909291908301828280156104eb57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116104cd575b5050505050815260200160028201548152602001600382015481526020016004820154815250509050600060036000836040015181526020019081526020016000206040518060a0016040529081600082015481526020016001820180548060200260200160405190810160405280929190818152602001828054801561059b57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161057d575b50505050508152602001600282015481526020016003820154815260200160048201548152505090506000805b83516001101561074057606084015160009081526007602090815260408083206001600160a01b038a168452909152812054905485510361063b578451600090815260086020526040902054600a5461062a90600361090960911b01316116af565b61063491906116c8565b925061063f565b8192505b608085015161064e828561170a565b6106589190611721565b61066290876116af565b84516000908152600860205260408082205488518352912054919750610687916116c8565b915083945060036000866040015181526020019081526020016000206040518060a0016040529081600082015481526020016001820180548060200260200160405190810160405280929190818152602001828054801561071157602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116106f3575b5050505050815260200160028201548152602001600382015481526020016004820154815250509350506105c8565b6001600160a01b03861660009081526009602052604090205461076390866116c8565b9695505050505050565b600080610778610c3b565b905060005b8160200151518110156107dc57816020015181815181106107a0576107a06116db565b60200260200101516001600160a01b0316846001600160a01b0316036107ca575060019392505050565b806107d4816116f1565b91505061077d565b5060009392505050565b6108186040518060a0016040528060008152602001606081526020016000815260200160008152602001600081525090565b60005482106108c65760008054815260036020908152604091829020825160a081018452815481526001820180548551818602810186019096528086529194929385810193929083018282801561089857602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161087a575b5050505050815260200160028201548152602001600382015481526020016004820154815250509050919050565b6000545b808310156108e9576000908152600360205260409020600201546108ca565b600081815260036020908152604091829020825160a081018452815481526001820180548551818602810186019096528086529194929385810193929083018282801561095f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610941575b505050505081526020016002820154815260200160038201548152602001600482015481525050915050919050565b6109973361076d565b6109d85760405162461bcd60e51b815260206004820152600d60248201526c4e6f7420436f6e73656e73757360981b60448201526064015b60405180910390fd5b438211610a1d5760405162461bcd60e51b81526020600482015260136024820152721a5b9d985b1a59081cdd185c9d12195a59da1d606a1b60448201526064016109cf565b6000815111610a665760405162461bcd60e51b81526020600482015260156024820152741a5b9d985b1a59081b5a5b995c9cc81b195b99da1d605a1b60448201526064016109cf565b600181511115610b305760005b60018251610a8191906116c8565b811015610b2e5781610a948260016116af565b81518110610aa457610aa46116db565b60200260200101516001600160a01b0316828281518110610ac757610ac76116db565b60200260200101516001600160a01b031610610b1c5760405162461bcd60e51b815260206004820152601460248201527334b73b30b634b21036b4b732b9399037b93232b960611b60448201526064016109cf565b80610b26816116f1565b915050610a73565b505b6000544311610b905760405162461bcd60e51b815260206004820152602660248201527f70726f706f73652073686f756c64206166746572206c6173742070686173652060448201526561637469766560d01b60648201526084016109cf565b60028054906000610ba0836116f1565b9091555050604080516060810182526002805480835260208084018781528486018781526000938452600483529590922084518155915160018301559351805193949193610bf59385019291909101906113ac565b50506002546040517ff38d9003e16b18afebcec1c73fd3f4d644825e76e36c4326af56aaddadd5545f9250610c2f91339186908690611743565b60405180910390a15050565b610c6d6040518060a0016040528060008152602001606081526020016000815260200160008152602001600081525090565b610c76436107e6565b905090565b6002600b5403610c9d5760405162461bcd60e51b81526004016109cf90611770565b6002600b556001548210801590610cb657506002548211155b610cf45760405162461bcd60e51b815260206004820152600f60248201526e1a5b9d985b1a5908191c98599d1259608a1b60448201526064016109cf565b6000828152600460205260409020600101544310610d545760405162461bcd60e51b815260206004820152601a60248201527f696e76616c69642064726166742073746172742068656967687400000000000060448201526064016109cf565b670de0b6b3a7640000811015610da25760405162461bcd60e51b81526020600482015260136024820152721a5b9cdd59999a58da595b9d08185b5bdd5b9d606a1b60448201526064016109cf565b80341015610de75760405162461bcd60e51b8152602060048201526012602482015271696e73756666696369656e742076616c756560701b60448201526064016109cf565b600082815260056020908152604080832033845290915281208054839290610e109084906116af565b9091555050600082815260076020908152604080832033845290915281208054839290610e3e9084906116af565b909155505060008281526006602052604081208054839290610e619084906116af565b909155505060408051338152602081018490529081018290527fafd3f234c1f8e944129b26b206d98e5752ad3336a4059938b4a3e990e95885309060600160405180910390a16000828152600660205260409020546a027b46536c66c8e30000008110611062576000838152600460209081526040808320815160608101835281548152600182015481850152600282018054845181870281018701865281815292959394860193830182828015610f4257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f24575b5050509190925250506040805160a081018252602080850180518352838601518284019081526000805485870152606085018c9052608085018a9052915182526003835293902082518155925180519596509194859450610fa992600185019201906113ac565b50604082015160028083019190915560608301516003830155608090920151600490910155602083015160005554610fe29060016116af565b600155600a54610ffb90600361090960911b01316116af565b6008600084602001518152602001908152602001600020819055507f5606b7fb750b4fb80525cd923da18033c8a8b8e99a2923bd13eae424a615742f8382600001518360200151846040015160405161105794939291906117a7565b60405180910390a150505b8134111561107d5761107d3361107884346116c8565b6112de565b50506001600b5550565b6002600b54036110a95760405162461bcd60e51b81526004016109cf90611770565b6002600b5560006110b933610473565b9050801561115e5733600090815260096020526040812080548392906110e09084906116af565b9250508190555080600a60008282546110f991906116af565b909155505060405163f3fef3a360e01b815233600482015260248101829052600361090960911b019063f3fef3a390604401600060405180830381600087803b15801561114557600080fd5b505af1158015611159573d6000803e3d6000fd5b505050505b506001600b55565b6002600b54036111885760405162461bcd60e51b81526004016109cf90611770565b6002600b819055548111156111d15760405162461bcd60e51b815260206004820152600f60248201526e1a5b9d985b1a5908191c98599d1259608a1b60448201526064016109cf565b60008181526005602090815260408083203384529091529020548061122b5760405162461bcd60e51b815260206004820152601060248201526f656d70747920766f74652076616c756560801b60448201526064016109cf565b600082815260056020908152604080832033845282528083208390558483526006909152812080548392906112619084906116c8565b9091555050600154821061128a5760008281526007602090815260408083203384529091528120555b61129433826112de565b60408051338152602081018490529081018290527f7beea58284fafba3a35fa25c68eed786c8c83e3ebb2cfa48238aed72e1fe7dbd9060600160405180910390a150506001600b55565b604080516000808252602082019092526001600160a01b03841690839060405161130891906117d7565b60006040518083038185875af1925050503d8060008114611345576040519150601f19603f3d011682016040523d82523d6000602084013e61134a565b606091505b50509050806113a75760405162461bcd60e51b8152602060048201526024808201527f736166655472616e736665724554483a20455448207472616e736665722066616044820152631a5b195960e21b60648201526084016109cf565b505050565b828054828255906000526020600020908101928215611401579160200282015b8281111561140157825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906113cc565b5061140d929150611411565b5090565b5b8082111561140d5760008155600101611412565b600081518084526020808501945080840160005b8381101561145f5781516001600160a01b03168752958201959082019060010161143a565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b838110156114db57888303603f19018552815180518452878101518885015286015160608785018190526114c781860183611426565b968901969450505090860190600101611491565b509098975050505050505050565b80356001600160a01b038116811461150057600080fd5b919050565b60006020828403121561151757600080fd5b611520826114e9565b9392505050565b60006020828403121561153957600080fd5b5035919050565b60208152815160208201526000602083015160a0604084015261156660c0840182611426565b90506040840151606084015260608401516080840152608084015160a08401528091505092915050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156115b957600080fd5b8235915060208084013567ffffffffffffffff808211156115d957600080fd5b818601915086601f8301126115ed57600080fd5b8135818111156115ff576115ff611590565b8060051b604051601f19603f8301168101818110858211171561162457611624611590565b60405291825284820192508381018501918983111561164257600080fd5b938501935b8285101561166757611658856114e9565b84529385019392850192611647565b8096505050505050509250929050565b6000806040838503121561168a57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b808201808211156116c2576116c2611699565b92915050565b818103818111156116c2576116c2611699565b634e487b7160e01b600052603260045260246000fd5b60006001820161170357611703611699565b5060010190565b80820281158282048414176116c2576116c2611699565b60008261173e57634e487b7160e01b600052601260045260246000fd5b500490565b60018060a01b03851681528360208201528260408201526080606082015260006107636080830184611426565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b8481528360208201526080604082015260006117c66080830185611426565b905082606083015295945050505050565b6000825160005b818110156117f857602081860181015185830152016117de565b50600092019182525091905056fea26469706673582212206c395a19a9e4583bfaeb2ed6e0bdbb178ae9330eb7e55cca7937fd9bd450a57f64736f6c63430008120033" + "code": "60806040526004361061019f575f3560e01c8063786255f1116100eb5780639f9d7f8111610089578063b88a802f11610063578063b88a802f14610846578063d8ce95ab1461085c578063da0b331714610898578063db069ba5146108d457610458565b80639f9d7f81146107dc578063a6580de814610806578063a681dfec1461083057610458565b80638f1b3219116100c55780638f1b321914610724578063902bdc261461074e5780639690293b1461078a57806398ca58df146107a057610458565b8063786255f11461068257806389dc5c84146106be5780638e1900a8146106e857610458565b80634c569c2511610158578063611905331161013257806361190533146105ea578063683dd191146106005780636db504e71461062a5780636dd7d8ea1461066657610458565b80634c569c25146105485780634d21e426146105845780634ff0876a146105c057610458565b806303f187ea1461045c57806306a49fce146104865780630b2a85ea146104b05780630ea6a041146104cc5780631f26f2561461050857806343c14b221461053257610458565b36610458575f600d80548060200260200160405190810160405280929190818152602001828054801561022457602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116101db575b505050505090505f815190505f5b818110156104565760095f8483815181106102505761024f612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e85f54670de0b6b3a764000060065f8887815181106102b6576102b5612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20543461030391906126dc565b61030d91906126dc565b610317919061274a565b610321919061274a565b61032b919061274a565b600e5f85848151811061034157610340612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610390919061277a565b925050819055506104438382815181106103ad576103ac612679565b5b60200260200101516103e85f5460065f8887815181106103d0576103cf612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e861041f91906127ad565b3461042a91906126dc565b610434919061274a565b61043e919061274a565b610910565b808061044e906127e0565b915050610232565b005b5f80fd5b348015610467575f80fd5b50610470610a0b565b60405161047d9190612836565b60405180910390f35b348015610491575f80fd5b5061049a610a11565b6040516104a79190612936565b60405180910390f35b6104ca60048036038101906104c59190612984565b610a22565b005b3480156104d7575f80fd5b506104f260048036038101906104ed9190612984565b610c51565b6040516104ff91906129be565b60405180910390f35b348015610513575f80fd5b5061051c610c8c565b6040516105299190612836565b60405180910390f35b34801561053d575f80fd5b50610546610c92565b005b348015610553575f80fd5b5061056e60048036038101906105699190612a01565b610f72565b60405161057b9190612836565b60405180910390f35b34801561058f575f80fd5b506105aa60048036038101906105a59190612a01565b610f87565b6040516105b79190612836565b60405180910390f35b3480156105cb575f80fd5b506105d4610f9c565b6040516105e19190612836565b60405180910390f35b3480156105f5575f80fd5b506105fe610fa2565b005b34801561060b575f80fd5b50610614611189565b6040516106219190612836565b60405180910390f35b348015610635575f80fd5b50610650600480360381019061064b9190612a01565b611195565b60405161065d91906129be565b60405180910390f35b610680600480360381019061067b9190612a01565b6111c5565b005b34801561068d575f80fd5b506106a860048036038101906106a39190612a2c565b6115c5565b6040516106b59190612836565b60405180910390f35b3480156106c9575f80fd5b506106d26115e5565b6040516106df91906129be565b60405180910390f35b3480156106f3575f80fd5b5061070e60048036038101906107099190612a01565b6115fd565b60405161071b9190612836565b60405180910390f35b34801561072f575f80fd5b50610738611612565b6040516107459190612836565b60405180910390f35b348015610759575f80fd5b50610774600480360381019061076f9190612a01565b611618565b6040516107819190612836565b60405180910390f35b348015610795575f80fd5b5061079e61162d565b005b3480156107ab575f80fd5b506107c660048036038101906107c19190612a01565b611710565b6040516107d39190612836565b60405180910390f35b3480156107e7575f80fd5b506107f0611725565b6040516107fd9190612936565b60405180910390f35b348015610811575f80fd5b5061081a6117b0565b6040516108279190612836565b60405180910390f35b34801561083b575f80fd5b506108446117b5565b005b348015610851575f80fd5b5061085a611a1f565b005b348015610867575f80fd5b50610882600480360381019061087d9190612a01565b611afa565b60405161088f9190612836565b60405180910390f35b3480156108a3575f80fd5b506108be60048036038101906108b99190612a01565b611b0f565b6040516108cb9190612836565b60405180910390f35b3480156108df575f80fd5b506108fa60048036038101906108f59190612a01565b611b24565b6040516109079190612836565b60405180910390f35b5f8273ffffffffffffffffffffffffffffffffffffffff16825f67ffffffffffffffff81111561094357610942612a6a565b5b6040519080825280601f01601f1916602001820160405280156109755781602001600182028036833780820191505090505b506040516109839190612b03565b5f6040518083038185875af1925050503d805f81146109bd576040519150601f19603f3d011682016040523d82523d5f602084013e6109c2565b606091505b5050905080610a06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109fd90612b99565b60405180910390fd5b505050565b60025481565b6060610a1d6004611b39565b905090565b600254341015610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612c01565b60405180910390fd5b6103e88110610aab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa290612c69565b60405180910390fd5b610abf336004611b5890919063ffffffff16565b15610aff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610af690612cd1565b60405180910390fd5b5f60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205414610b7e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7590612d39565b60405180910390fd5b610b92336004611b8590919063ffffffff16565b508060065f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503460085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507feeda149c76076b34d4b9d8896c2f7efc0d33d1c7b53ea3c5db490d64613f603a33604051610c4691906129be565b60405180910390a150565b600d8181548110610c60575f80fd5b905f5260205f20015f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600c5481565b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015610d6e57505f81115b610dad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da490612da1565b60405180910390fd5b610db73383611bb2565b8060095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610e0391906127ad565b92505081905550600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9055600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905560105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9055610f333382610910565b7fb698e31a2abee5824d0d7bcfd2339aead7f9e9ae413fba50bf554ff3fa470b7b338383604051610f6693929190612dbf565b60405180910390a15050565b600e602052805f5260405f205f915090505481565b6008602052805f5260405f205f915090505481565b60035481565b5f60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205411801561104357506003546002610ff891906126dc565b60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054611040919061277a565b43115b611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107990612e3e565b60405180910390fd5b5f60085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905060085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905560075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905561114d3382610910565b7f142e26dcca50281d2c46d90446bfc1c9bc260cef355ce917a52f1fec7c54b5bf338260405161117e929190612e5c565b60405180910390a150565b670de0b6b3a764000081565b600a602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015434101561120a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120190612c01565b60405180910390fd5b61121e816004611b5890919063ffffffff16565b61125d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161125490612ecd565b60405180910390fd5b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061132257505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611361576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135890612f35565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146113a35761139e3382611bb2565b61149e565b81600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600e5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505b34600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546114ea919061277a565b925050819055503460095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461153d919061277a565b925050819055504360105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc3383346040516115b993929190612dbf565b60405180910390a15050565b6011602052815f5260405f20602052805f5260405f205f91509150505481565b73121200000000000000000000000000000000000381565b600f602052805f5260405f205f915090505481565b60015481565b6006602052805f5260405f205f915090505481565b611641336004611b5890919063ffffffff16565b611680576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161167790612f9d565b60405180910390fd5b611694336004611e5d90919063ffffffff16565b504360075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507f7c79e6e24ed041d1072d54523b53956f01b91b835f0490856370594d9d14470e3360405161170691906129be565b60405180910390a1565b6010602052805f5260405f205f915090505481565b6060600d8054806020026020016040519081016040528092919081815260200182805480156117a657602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161175d575b5050505050905090565b5f5481565b73fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611837576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161182e90613005565b60405180910390fd5b600354600c54611847919061277a565b4310611a1d5773121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156118a6575f80fd5b505af11580156118b8573d5f803e3d5ffd5b505050505f6118c76004611b39565b90505f815190505f5b818110156119bc57600e5f8483815181106118ee576118ed612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205460115f85848151811061194657611945612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f600354600c54611998919061274a565b81526020019081526020015f208190555080806119b4906127e0565b9150506118d0565b5043600c819055506119cc611e8a565b600d90805190602001906119e19291906125d7565b507fe59e3b36b5c97b419925b60c92f5a4324c993934eb9cfe5232def67c1739337c600d604051611a129190613103565b60405180910390a150505b565b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611aed576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ae49061316d565b60405180910390fd5b611af73382611bb2565b50565b6009602052805f5260405f205f915090505481565b6007602052805f5260405f205f915090505481565b600b602052805f5260405f205f915090505481565b60605f611b47835f01612067565b905060608190508092505050919050565b5f611b7d835f018373ffffffffffffffffffffffffffffffffffffffff165f1b6120c0565b905092915050565b5f611baa835f018373ffffffffffffffffffffffffffffffffffffffff165f1b6120e0565b905092915050565b73121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611c0b575f80fd5b505af1158015611c1d573d5f803e3d5ffd5b505050505f60105f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f600f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f600e5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f60115f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6001600354600188611d3591906127ad565b611d3f919061274a565b611d49919061277a565b81526020019081526020015f2054905082811115611d65578092505b5f670de0b6b3a76400008484611d7b91906127ad565b600b5f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054611dc391906126dc565b611dcd919061274a565b905082600f5f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550611e1b8782610910565b7fbeceb521ccd2816457290c3d1cb70cc1537f14307f2d9ac26a5093a38ea409488782604051611e4c929190612e5c565b60405180910390a150505050505050565b5f611e82835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612147565b905092915050565b60605f611e95610a11565b90505f815190505f8167ffffffffffffffff811115611eb757611eb6612a6a565b5b604051908082528060200260200182016040528015611ee55781602001602082028036833780820191505090505b5090505f5b82811015611f7c5760095f858381518110611f0857611f07612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054828281518110611f5d57611f5c612679565b5b6020026020010181815250508080611f74906127e0565b915050611eea565b50611f8983825f54612243565b5f805467ffffffffffffffff811115611fa557611fa4612a6a565b5b604051908082528060200260200182016040528015611fd35781602001602082028036833780820191505090505b5090505f5b5f5481101561205c57848181518110611ff457611ff3612679565b5b602002602001015182828151811061200f5761200e612679565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080612054906127e0565b915050611fd8565b508094505050505090565b6060815f018054806020026020016040519081016040528092919081815260200182805480156120b457602002820191905f5260205f20905b8154815260200190600101908083116120a0575b50505050509050919050565b5f80836001015f8481526020019081526020015f20541415905092915050565b5f6120eb83836120c0565b61213d57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f208190555060019050612141565b5f90505b92915050565b5f80836001015f8481526020019081526020015f205490505f8114612238575f60018261217491906127ad565b90505f6001865f018054905061218a91906127ad565b90508082146121f0575f865f0182815481106121a9576121a8612679565b5b905f5260205f200154905080875f0184815481106121ca576121c9612679565b5b905f5260205f20018190555083876001015f8381526020019081526020015f2081905550505b855f018054806122035761220261318b565b5b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f90556001935050505061223d565b5f9150505b92915050565b5f835190505f600160028461225891906131c1565b6122629190613229565b90505b5f811261228b576122788585838661239e565b808061228390613269565b915050612265565b505f8290505b8181101561239757835f815181106122ac576122ab612679565b5b60200260200101518482815181106122c7576122c6612679565b5b60200260200101511115612384578381815181106122e8576122e7612679565b5b6020026020010151845f8151811061230357612302612679565b5b60200260200101818152505084818151811061232257612321612679565b5b6020026020010151855f8151811061233d5761233c612679565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061238385855f8661239e565b5b808061238f906127e0565b915050612291565b5050505050565b5f60018360026123ae91906126dc565b6123b8919061277a565b90505b818110156125d057816001826123d1919061277a565b10801561241d5750836001826123e7919061277a565b815181106123f8576123f7612679565b5b602002602001015184828151811061241357612412612679565b5b6020026020010151115b156124325760018161242f919061277a565b90505b83838151811061244557612444612679565b5b60200260200101518482815181106124605761245f612679565b5b6020026020010151116125d0578383815181106124805761247f612679565b5b602002602001015184828151811061249b5761249a612679565b5b60200260200101518583815181106124b6576124b5612679565b5b602002602001018686815181106124d0576124cf612679565b5b60200260200101828152508281525050508483815181106124f4576124f3612679565b5b602002602001015185828151811061250f5761250e612679565b5b602002602001015186838151811061252a57612529612679565b5b6020026020010187868151811061254457612543612679565b5b602002602001018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250505080925060016002826125bf91906126dc565b6125c9919061277a565b90506123bb565b5050505050565b828054828255905f5260205f2090810192821561264d579160200282015b8281111561264c578251825f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906125f5565b5b50905061265a919061265e565b5090565b5b80821115612675575f815f90555060010161265f565b5090565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6126e6826126a6565b91506126f1836126a6565b92508282026126ff816126a6565b91508282048414831517612716576127156126af565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612754826126a6565b915061275f836126a6565b92508261276f5761276e61271d565b5b828204905092915050565b5f612784826126a6565b915061278f836126a6565b92508282019050808211156127a7576127a66126af565b5b92915050565b5f6127b7826126a6565b91506127c2836126a6565b92508282039050818111156127da576127d96126af565b5b92915050565b5f6127ea826126a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361281c5761281b6126af565b5b600182019050919050565b612830816126a6565b82525050565b5f6020820190506128495f830184612827565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6128a182612878565b9050919050565b6128b181612897565b82525050565b5f6128c283836128a8565b60208301905092915050565b5f602082019050919050565b5f6128e48261284f565b6128ee8185612859565b93506128f983612869565b805f5b8381101561292957815161291088826128b7565b975061291b836128ce565b9250506001810190506128fc565b5085935050505092915050565b5f6020820190508181035f83015261294e81846128da565b905092915050565b5f80fd5b612963816126a6565b811461296d575f80fd5b50565b5f8135905061297e8161295a565b92915050565b5f6020828403121561299957612998612956565b5b5f6129a684828501612970565b91505092915050565b6129b881612897565b82525050565b5f6020820190506129d15f8301846129af565b92915050565b6129e081612897565b81146129ea575f80fd5b50565b5f813590506129fb816129d7565b92915050565b5f60208284031215612a1657612a15612956565b5b5f612a23848285016129ed565b91505092915050565b5f8060408385031215612a4257612a41612956565b5b5f612a4f858286016129ed565b9250506020612a6085828601612970565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f81519050919050565b5f81905092915050565b5f5b83811015612ac8578082015181840152602081019050612aad565b5f8484015250505050565b5f612add82612a97565b612ae78185612aa1565b9350612af7818560208601612aab565b80840191505092915050565b5f612b0e8284612ad3565b915081905092915050565b5f82825260208201905092915050565b7f736166655472616e736665724554483a20455448207472616e736665722066615f8201527f696c656400000000000000000000000000000000000000000000000000000000602082015250565b5f612b83602483612b19565b9150612b8e82612b29565b604082019050919050565b5f6020820190508181035f830152612bb081612b77565b9050919050565b7f696e73756666696369656e7420616d6f756e74000000000000000000000000005f82015250565b5f612beb601383612b19565b9150612bf682612bb7565b602082019050919050565b5f6020820190508181035f830152612c1881612bdf565b9050919050565b7f696e76616c6964207261746500000000000000000000000000000000000000005f82015250565b5f612c53600c83612b19565b9150612c5e82612c1f565b602082019050919050565b5f6020820190508181035f830152612c8081612c47565b9050919050565b7f63616e64696461746520657869737473000000000000000000000000000000005f82015250565b5f612cbb601083612b19565b9150612cc682612c87565b602082019050919050565b5f6020820190508181035f830152612ce881612caf565b9050919050565b7f6c656674206e6f7420636c61696d6564000000000000000000000000000000005f82015250565b5f612d23601083612b19565b9150612d2e82612cef565b602082019050919050565b5f6020820190508181035f830152612d5081612d17565b9050919050565b7f7265766f6b65206e6f7420616c6c6f77656400000000000000000000000000005f82015250565b5f612d8b601283612b19565b9150612d9682612d57565b602082019050919050565b5f6020820190508181035f830152612db881612d7f565b9050919050565b5f606082019050612dd25f8301866129af565b612ddf60208301856129af565b612dec6040830184612827565b949350505050565b7f7769746864726177206e6f7420616c6c6f7765640000000000000000000000005f82015250565b5f612e28601483612b19565b9150612e3382612df4565b602082019050919050565b5f6020820190508181035f830152612e5581612e1c565b9050919050565b5f604082019050612e6f5f8301856129af565b612e7c6020830184612827565b9392505050565b7f63616e646964617465206e6f7420616c6c6f77656400000000000000000000005f82015250565b5f612eb7601583612b19565b9150612ec282612e83565b602082019050919050565b5f6020820190508181035f830152612ee481612eab565b9050919050565b7f6f6e6c79206f6e652063686f69636520697320616c6c6f7765640000000000005f82015250565b5f612f1f601a83612b19565b9150612f2a82612eeb565b602082019050919050565b5f6020820190508181035f830152612f4c81612f13565b9050919050565b7f63616e646964617465206e6f74206578697374730000000000000000000000005f82015250565b5f612f87601483612b19565b9150612f9282612f53565b602082019050919050565b5f6020820190508181035f830152612fb481612f7b565b9050919050565b7f736964652063616c6c206e6f7420616c6c6f77656400000000000000000000005f82015250565b5f612fef601583612b19565b9150612ffa82612fbb565b602082019050919050565b5f6020820190508181035f83015261301c81612fe3565b9050919050565b5f81549050919050565b5f819050815f5260205f209050919050565b5f815f1c9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61307b6130768361303f565b61304a565b9050919050565b5f61308d8254613069565b9050919050565b5f600182019050919050565b5f6130aa82613023565b6130b48185612859565b93506130bf8361302d565b805f5b838110156130f6576130d382613082565b6130dd88826128b7565b97506130e883613094565b9250506001810190506130c2565b5085935050505092915050565b5f6020820190508181035f83015261311b81846130a0565b905092915050565b7f636c61696d206e6f7420616c6c6f7765640000000000000000000000000000005f82015250565b5f613157601183612b19565b915061316282613123565b602082019050919050565b5f6020820190508181035f8301526131848161314b565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f819050919050565b5f6131cb826131b8565b91506131d6836131b8565b9250826131e6576131e561271d565b5b60015f0383147f80000000000000000000000000000000000000000000000000000000000000008314161561321e5761321d6126af565b5b828205905092915050565b5f613233826131b8565b915061323e836131b8565b925082820390508181125f8412168282135f851215161715613263576132626126af565b5b92915050565b5f613273826131b8565b91507f800000000000000000000000000000000000000000000000000000000000000082036132a5576132a46126af565b5b60018203905091905056fea26469706673582212208754f76bcef83fcbb689a0e1dc0402efe99293e1de0da2d989454aeaaecf362864736f6c63430008140033" }, "0x1212100000000000000000000000000000000002": { "balance": "0", From 19ce23d042cdfa141433110ae24a6018c5998f81 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Sat, 23 Mar 2024 00:01:28 +0800 Subject: [PATCH 54/66] fix genesis file --- genesis.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/genesis.json b/genesis.json index b434fc63f7..2cbbf7c5cf 100644 --- a/genesis.json +++ b/genesis.json @@ -51,7 +51,9 @@ "0xd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb8": "0xc51964013acbc6b271feecb0febd9e7a01202930", "0xd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb9": "0xc5bbd9652546bc96be3dec97a38ee335f7873dfa", "0xd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eba": "0x26f1794b81df2b832545b8b6bbca196b82e4feb1", - "0xd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1ebb": "0x0b51369d02e47ee3f143391b837aa08c31aaa19b" + "0xd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1ebb": "0x0b51369d02e47ee3f143391b837aa08c31aaa19b", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x1212100000000000000000000000000000000001", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x1212000000000000000000000000000000000000" } }, "0x1212000000000000000000000000000000000002": { @@ -69,7 +71,7 @@ }, "0x1212100000000000000000000000000000000001": { "balance": "0", - "code": "60806040526004361061019f575f3560e01c8063786255f1116100eb5780639f9d7f8111610089578063b88a802f11610063578063b88a802f14610846578063d8ce95ab1461085c578063da0b331714610898578063db069ba5146108d457610458565b80639f9d7f81146107dc578063a6580de814610806578063a681dfec1461083057610458565b80638f1b3219116100c55780638f1b321914610724578063902bdc261461074e5780639690293b1461078a57806398ca58df146107a057610458565b8063786255f11461068257806389dc5c84146106be5780638e1900a8146106e857610458565b80634c569c2511610158578063611905331161013257806361190533146105ea578063683dd191146106005780636db504e71461062a5780636dd7d8ea1461066657610458565b80634c569c25146105485780634d21e426146105845780634ff0876a146105c057610458565b806303f187ea1461045c57806306a49fce146104865780630b2a85ea146104b05780630ea6a041146104cc5780631f26f2561461050857806343c14b221461053257610458565b36610458575f600d80548060200260200160405190810160405280929190818152602001828054801561022457602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116101db575b505050505090505f815190505f5b818110156104565760095f8483815181106102505761024f612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e85f54670de0b6b3a764000060065f8887815181106102b6576102b5612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20543461030391906126dc565b61030d91906126dc565b610317919061274a565b610321919061274a565b61032b919061274a565b600e5f85848151811061034157610340612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610390919061277a565b925050819055506104438382815181106103ad576103ac612679565b5b60200260200101516103e85f5460065f8887815181106103d0576103cf612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e861041f91906127ad565b3461042a91906126dc565b610434919061274a565b61043e919061274a565b610910565b808061044e906127e0565b915050610232565b005b5f80fd5b348015610467575f80fd5b50610470610a0b565b60405161047d9190612836565b60405180910390f35b348015610491575f80fd5b5061049a610a11565b6040516104a79190612936565b60405180910390f35b6104ca60048036038101906104c59190612984565b610a22565b005b3480156104d7575f80fd5b506104f260048036038101906104ed9190612984565b610c51565b6040516104ff91906129be565b60405180910390f35b348015610513575f80fd5b5061051c610c8c565b6040516105299190612836565b60405180910390f35b34801561053d575f80fd5b50610546610c92565b005b348015610553575f80fd5b5061056e60048036038101906105699190612a01565b610f72565b60405161057b9190612836565b60405180910390f35b34801561058f575f80fd5b506105aa60048036038101906105a59190612a01565b610f87565b6040516105b79190612836565b60405180910390f35b3480156105cb575f80fd5b506105d4610f9c565b6040516105e19190612836565b60405180910390f35b3480156105f5575f80fd5b506105fe610fa2565b005b34801561060b575f80fd5b50610614611189565b6040516106219190612836565b60405180910390f35b348015610635575f80fd5b50610650600480360381019061064b9190612a01565b611195565b60405161065d91906129be565b60405180910390f35b610680600480360381019061067b9190612a01565b6111c5565b005b34801561068d575f80fd5b506106a860048036038101906106a39190612a2c565b6115c5565b6040516106b59190612836565b60405180910390f35b3480156106c9575f80fd5b506106d26115e5565b6040516106df91906129be565b60405180910390f35b3480156106f3575f80fd5b5061070e60048036038101906107099190612a01565b6115fd565b60405161071b9190612836565b60405180910390f35b34801561072f575f80fd5b50610738611612565b6040516107459190612836565b60405180910390f35b348015610759575f80fd5b50610774600480360381019061076f9190612a01565b611618565b6040516107819190612836565b60405180910390f35b348015610795575f80fd5b5061079e61162d565b005b3480156107ab575f80fd5b506107c660048036038101906107c19190612a01565b611710565b6040516107d39190612836565b60405180910390f35b3480156107e7575f80fd5b506107f0611725565b6040516107fd9190612936565b60405180910390f35b348015610811575f80fd5b5061081a6117b0565b6040516108279190612836565b60405180910390f35b34801561083b575f80fd5b506108446117b5565b005b348015610851575f80fd5b5061085a611a1f565b005b348015610867575f80fd5b50610882600480360381019061087d9190612a01565b611afa565b60405161088f9190612836565b60405180910390f35b3480156108a3575f80fd5b506108be60048036038101906108b99190612a01565b611b0f565b6040516108cb9190612836565b60405180910390f35b3480156108df575f80fd5b506108fa60048036038101906108f59190612a01565b611b24565b6040516109079190612836565b60405180910390f35b5f8273ffffffffffffffffffffffffffffffffffffffff16825f67ffffffffffffffff81111561094357610942612a6a565b5b6040519080825280601f01601f1916602001820160405280156109755781602001600182028036833780820191505090505b506040516109839190612b03565b5f6040518083038185875af1925050503d805f81146109bd576040519150601f19603f3d011682016040523d82523d5f602084013e6109c2565b606091505b5050905080610a06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109fd90612b99565b60405180910390fd5b505050565b60025481565b6060610a1d6004611b39565b905090565b600254341015610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612c01565b60405180910390fd5b6103e88110610aab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa290612c69565b60405180910390fd5b610abf336004611b5890919063ffffffff16565b15610aff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610af690612cd1565b60405180910390fd5b5f60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205414610b7e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7590612d39565b60405180910390fd5b610b92336004611b8590919063ffffffff16565b508060065f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503460085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507feeda149c76076b34d4b9d8896c2f7efc0d33d1c7b53ea3c5db490d64613f603a33604051610c4691906129be565b60405180910390a150565b600d8181548110610c60575f80fd5b905f5260205f20015f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600c5481565b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015610d6e57505f81115b610dad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da490612da1565b60405180910390fd5b610db73383611bb2565b8060095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610e0391906127ad565b92505081905550600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9055600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905560105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9055610f333382610910565b7fb698e31a2abee5824d0d7bcfd2339aead7f9e9ae413fba50bf554ff3fa470b7b338383604051610f6693929190612dbf565b60405180910390a15050565b600e602052805f5260405f205f915090505481565b6008602052805f5260405f205f915090505481565b60035481565b5f60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205411801561104357506003546002610ff891906126dc565b60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054611040919061277a565b43115b611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107990612e3e565b60405180910390fd5b5f60085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905060085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905560075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905561114d3382610910565b7f142e26dcca50281d2c46d90446bfc1c9bc260cef355ce917a52f1fec7c54b5bf338260405161117e929190612e5c565b60405180910390a150565b670de0b6b3a764000081565b600a602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015434101561120a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120190612c01565b60405180910390fd5b61121e816004611b5890919063ffffffff16565b61125d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161125490612ecd565b60405180910390fd5b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061132257505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611361576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135890612f35565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146113a35761139e3382611bb2565b61149e565b81600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600e5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505b34600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546114ea919061277a565b925050819055503460095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461153d919061277a565b925050819055504360105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc3383346040516115b993929190612dbf565b60405180910390a15050565b6011602052815f5260405f20602052805f5260405f205f91509150505481565b73121200000000000000000000000000000000000381565b600f602052805f5260405f205f915090505481565b60015481565b6006602052805f5260405f205f915090505481565b611641336004611b5890919063ffffffff16565b611680576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161167790612f9d565b60405180910390fd5b611694336004611e5d90919063ffffffff16565b504360075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507f7c79e6e24ed041d1072d54523b53956f01b91b835f0490856370594d9d14470e3360405161170691906129be565b60405180910390a1565b6010602052805f5260405f205f915090505481565b6060600d8054806020026020016040519081016040528092919081815260200182805480156117a657602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161175d575b5050505050905090565b5f5481565b73fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611837576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161182e90613005565b60405180910390fd5b600354600c54611847919061277a565b4310611a1d5773121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156118a6575f80fd5b505af11580156118b8573d5f803e3d5ffd5b505050505f6118c76004611b39565b90505f815190505f5b818110156119bc57600e5f8483815181106118ee576118ed612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205460115f85848151811061194657611945612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f600354600c54611998919061274a565b81526020019081526020015f208190555080806119b4906127e0565b9150506118d0565b5043600c819055506119cc611e8a565b600d90805190602001906119e19291906125d7565b507fe59e3b36b5c97b419925b60c92f5a4324c993934eb9cfe5232def67c1739337c600d604051611a129190613103565b60405180910390a150505b565b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611aed576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ae49061316d565b60405180910390fd5b611af73382611bb2565b50565b6009602052805f5260405f205f915090505481565b6007602052805f5260405f205f915090505481565b600b602052805f5260405f205f915090505481565b60605f611b47835f01612067565b905060608190508092505050919050565b5f611b7d835f018373ffffffffffffffffffffffffffffffffffffffff165f1b6120c0565b905092915050565b5f611baa835f018373ffffffffffffffffffffffffffffffffffffffff165f1b6120e0565b905092915050565b73121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611c0b575f80fd5b505af1158015611c1d573d5f803e3d5ffd5b505050505f60105f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f600f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f600e5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f60115f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6001600354600188611d3591906127ad565b611d3f919061274a565b611d49919061277a565b81526020019081526020015f2054905082811115611d65578092505b5f670de0b6b3a76400008484611d7b91906127ad565b600b5f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054611dc391906126dc565b611dcd919061274a565b905082600f5f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550611e1b8782610910565b7fbeceb521ccd2816457290c3d1cb70cc1537f14307f2d9ac26a5093a38ea409488782604051611e4c929190612e5c565b60405180910390a150505050505050565b5f611e82835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612147565b905092915050565b60605f611e95610a11565b90505f815190505f8167ffffffffffffffff811115611eb757611eb6612a6a565b5b604051908082528060200260200182016040528015611ee55781602001602082028036833780820191505090505b5090505f5b82811015611f7c5760095f858381518110611f0857611f07612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054828281518110611f5d57611f5c612679565b5b6020026020010181815250508080611f74906127e0565b915050611eea565b50611f8983825f54612243565b5f805467ffffffffffffffff811115611fa557611fa4612a6a565b5b604051908082528060200260200182016040528015611fd35781602001602082028036833780820191505090505b5090505f5b5f5481101561205c57848181518110611ff457611ff3612679565b5b602002602001015182828151811061200f5761200e612679565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080612054906127e0565b915050611fd8565b508094505050505090565b6060815f018054806020026020016040519081016040528092919081815260200182805480156120b457602002820191905f5260205f20905b8154815260200190600101908083116120a0575b50505050509050919050565b5f80836001015f8481526020019081526020015f20541415905092915050565b5f6120eb83836120c0565b61213d57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f208190555060019050612141565b5f90505b92915050565b5f80836001015f8481526020019081526020015f205490505f8114612238575f60018261217491906127ad565b90505f6001865f018054905061218a91906127ad565b90508082146121f0575f865f0182815481106121a9576121a8612679565b5b905f5260205f200154905080875f0184815481106121ca576121c9612679565b5b905f5260205f20018190555083876001015f8381526020019081526020015f2081905550505b855f018054806122035761220261318b565b5b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f90556001935050505061223d565b5f9150505b92915050565b5f835190505f600160028461225891906131c1565b6122629190613229565b90505b5f811261228b576122788585838661239e565b808061228390613269565b915050612265565b505f8290505b8181101561239757835f815181106122ac576122ab612679565b5b60200260200101518482815181106122c7576122c6612679565b5b60200260200101511115612384578381815181106122e8576122e7612679565b5b6020026020010151845f8151811061230357612302612679565b5b60200260200101818152505084818151811061232257612321612679565b5b6020026020010151855f8151811061233d5761233c612679565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061238385855f8661239e565b5b808061238f906127e0565b915050612291565b5050505050565b5f60018360026123ae91906126dc565b6123b8919061277a565b90505b818110156125d057816001826123d1919061277a565b10801561241d5750836001826123e7919061277a565b815181106123f8576123f7612679565b5b602002602001015184828151811061241357612412612679565b5b6020026020010151115b156124325760018161242f919061277a565b90505b83838151811061244557612444612679565b5b60200260200101518482815181106124605761245f612679565b5b6020026020010151116125d0578383815181106124805761247f612679565b5b602002602001015184828151811061249b5761249a612679565b5b60200260200101518583815181106124b6576124b5612679565b5b602002602001018686815181106124d0576124cf612679565b5b60200260200101828152508281525050508483815181106124f4576124f3612679565b5b602002602001015185828151811061250f5761250e612679565b5b602002602001015186838151811061252a57612529612679565b5b6020026020010187868151811061254457612543612679565b5b602002602001018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250505080925060016002826125bf91906126dc565b6125c9919061277a565b90506123bb565b5050505050565b828054828255905f5260205f2090810192821561264d579160200282015b8281111561264c578251825f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906125f5565b5b50905061265a919061265e565b5090565b5b80821115612675575f815f90555060010161265f565b5090565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6126e6826126a6565b91506126f1836126a6565b92508282026126ff816126a6565b91508282048414831517612716576127156126af565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612754826126a6565b915061275f836126a6565b92508261276f5761276e61271d565b5b828204905092915050565b5f612784826126a6565b915061278f836126a6565b92508282019050808211156127a7576127a66126af565b5b92915050565b5f6127b7826126a6565b91506127c2836126a6565b92508282039050818111156127da576127d96126af565b5b92915050565b5f6127ea826126a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361281c5761281b6126af565b5b600182019050919050565b612830816126a6565b82525050565b5f6020820190506128495f830184612827565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6128a182612878565b9050919050565b6128b181612897565b82525050565b5f6128c283836128a8565b60208301905092915050565b5f602082019050919050565b5f6128e48261284f565b6128ee8185612859565b93506128f983612869565b805f5b8381101561292957815161291088826128b7565b975061291b836128ce565b9250506001810190506128fc565b5085935050505092915050565b5f6020820190508181035f83015261294e81846128da565b905092915050565b5f80fd5b612963816126a6565b811461296d575f80fd5b50565b5f8135905061297e8161295a565b92915050565b5f6020828403121561299957612998612956565b5b5f6129a684828501612970565b91505092915050565b6129b881612897565b82525050565b5f6020820190506129d15f8301846129af565b92915050565b6129e081612897565b81146129ea575f80fd5b50565b5f813590506129fb816129d7565b92915050565b5f60208284031215612a1657612a15612956565b5b5f612a23848285016129ed565b91505092915050565b5f8060408385031215612a4257612a41612956565b5b5f612a4f858286016129ed565b9250506020612a6085828601612970565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f81519050919050565b5f81905092915050565b5f5b83811015612ac8578082015181840152602081019050612aad565b5f8484015250505050565b5f612add82612a97565b612ae78185612aa1565b9350612af7818560208601612aab565b80840191505092915050565b5f612b0e8284612ad3565b915081905092915050565b5f82825260208201905092915050565b7f736166655472616e736665724554483a20455448207472616e736665722066615f8201527f696c656400000000000000000000000000000000000000000000000000000000602082015250565b5f612b83602483612b19565b9150612b8e82612b29565b604082019050919050565b5f6020820190508181035f830152612bb081612b77565b9050919050565b7f696e73756666696369656e7420616d6f756e74000000000000000000000000005f82015250565b5f612beb601383612b19565b9150612bf682612bb7565b602082019050919050565b5f6020820190508181035f830152612c1881612bdf565b9050919050565b7f696e76616c6964207261746500000000000000000000000000000000000000005f82015250565b5f612c53600c83612b19565b9150612c5e82612c1f565b602082019050919050565b5f6020820190508181035f830152612c8081612c47565b9050919050565b7f63616e64696461746520657869737473000000000000000000000000000000005f82015250565b5f612cbb601083612b19565b9150612cc682612c87565b602082019050919050565b5f6020820190508181035f830152612ce881612caf565b9050919050565b7f6c656674206e6f7420636c61696d6564000000000000000000000000000000005f82015250565b5f612d23601083612b19565b9150612d2e82612cef565b602082019050919050565b5f6020820190508181035f830152612d5081612d17565b9050919050565b7f7265766f6b65206e6f7420616c6c6f77656400000000000000000000000000005f82015250565b5f612d8b601283612b19565b9150612d9682612d57565b602082019050919050565b5f6020820190508181035f830152612db881612d7f565b9050919050565b5f606082019050612dd25f8301866129af565b612ddf60208301856129af565b612dec6040830184612827565b949350505050565b7f7769746864726177206e6f7420616c6c6f7765640000000000000000000000005f82015250565b5f612e28601483612b19565b9150612e3382612df4565b602082019050919050565b5f6020820190508181035f830152612e5581612e1c565b9050919050565b5f604082019050612e6f5f8301856129af565b612e7c6020830184612827565b9392505050565b7f63616e646964617465206e6f7420616c6c6f77656400000000000000000000005f82015250565b5f612eb7601583612b19565b9150612ec282612e83565b602082019050919050565b5f6020820190508181035f830152612ee481612eab565b9050919050565b7f6f6e6c79206f6e652063686f69636520697320616c6c6f7765640000000000005f82015250565b5f612f1f601a83612b19565b9150612f2a82612eeb565b602082019050919050565b5f6020820190508181035f830152612f4c81612f13565b9050919050565b7f63616e646964617465206e6f74206578697374730000000000000000000000005f82015250565b5f612f87601483612b19565b9150612f9282612f53565b602082019050919050565b5f6020820190508181035f830152612fb481612f7b565b9050919050565b7f736964652063616c6c206e6f7420616c6c6f77656400000000000000000000005f82015250565b5f612fef601583612b19565b9150612ffa82612fbb565b602082019050919050565b5f6020820190508181035f83015261301c81612fe3565b9050919050565b5f81549050919050565b5f819050815f5260205f209050919050565b5f815f1c9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61307b6130768361303f565b61304a565b9050919050565b5f61308d8254613069565b9050919050565b5f600182019050919050565b5f6130aa82613023565b6130b48185612859565b93506130bf8361302d565b805f5b838110156130f6576130d382613082565b6130dd88826128b7565b97506130e883613094565b9250506001810190506130c2565b5085935050505092915050565b5f6020820190508181035f83015261311b81846130a0565b905092915050565b7f636c61696d206e6f7420616c6c6f7765640000000000000000000000000000005f82015250565b5f613157601183612b19565b915061316282613123565b602082019050919050565b5f6020820190508181035f8301526131848161314b565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f819050919050565b5f6131cb826131b8565b91506131d6836131b8565b9250826131e6576131e561271d565b5b60015f0383147f80000000000000000000000000000000000000000000000000000000000000008314161561321e5761321d6126af565b5b828205905092915050565b5f613233826131b8565b915061323e836131b8565b925082820390508181125f8412168282135f851215161715613263576132626126af565b5b92915050565b5f613273826131b8565b91507f800000000000000000000000000000000000000000000000000000000000000082036132a5576132a46126af565b5b60018203905091905056fea26469706673582212208754f76bcef83fcbb689a0e1dc0402efe99293e1de0da2d989454aeaaecf362864736f6c63430008140033" + "code": "0x60806040526004361061019f575f3560e01c8063786255f1116100eb5780639f9d7f8111610089578063b88a802f11610063578063b88a802f14610846578063d8ce95ab1461085c578063da0b331714610898578063db069ba5146108d457610458565b80639f9d7f81146107dc578063a6580de814610806578063a681dfec1461083057610458565b80638f1b3219116100c55780638f1b321914610724578063902bdc261461074e5780639690293b1461078a57806398ca58df146107a057610458565b8063786255f11461068257806389dc5c84146106be5780638e1900a8146106e857610458565b80634c569c2511610158578063611905331161013257806361190533146105ea578063683dd191146106005780636db504e71461062a5780636dd7d8ea1461066657610458565b80634c569c25146105485780634d21e426146105845780634ff0876a146105c057610458565b806303f187ea1461045c57806306a49fce146104865780630b2a85ea146104b05780630ea6a041146104cc5780631f26f2561461050857806343c14b221461053257610458565b36610458575f600d80548060200260200160405190810160405280929190818152602001828054801561022457602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116101db575b505050505090505f815190505f5b818110156104565760095f8483815181106102505761024f612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e85f54670de0b6b3a764000060065f8887815181106102b6576102b5612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20543461030391906126dc565b61030d91906126dc565b610317919061274a565b610321919061274a565b61032b919061274a565b600e5f85848151811061034157610340612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610390919061277a565b925050819055506104438382815181106103ad576103ac612679565b5b60200260200101516103e85f5460065f8887815181106103d0576103cf612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e861041f91906127ad565b3461042a91906126dc565b610434919061274a565b61043e919061274a565b610910565b808061044e906127e0565b915050610232565b005b5f80fd5b348015610467575f80fd5b50610470610a0b565b60405161047d9190612836565b60405180910390f35b348015610491575f80fd5b5061049a610a11565b6040516104a79190612936565b60405180910390f35b6104ca60048036038101906104c59190612984565b610a22565b005b3480156104d7575f80fd5b506104f260048036038101906104ed9190612984565b610c51565b6040516104ff91906129be565b60405180910390f35b348015610513575f80fd5b5061051c610c8c565b6040516105299190612836565b60405180910390f35b34801561053d575f80fd5b50610546610c92565b005b348015610553575f80fd5b5061056e60048036038101906105699190612a01565b610f72565b60405161057b9190612836565b60405180910390f35b34801561058f575f80fd5b506105aa60048036038101906105a59190612a01565b610f87565b6040516105b79190612836565b60405180910390f35b3480156105cb575f80fd5b506105d4610f9c565b6040516105e19190612836565b60405180910390f35b3480156105f5575f80fd5b506105fe610fa2565b005b34801561060b575f80fd5b50610614611189565b6040516106219190612836565b60405180910390f35b348015610635575f80fd5b50610650600480360381019061064b9190612a01565b611195565b60405161065d91906129be565b60405180910390f35b610680600480360381019061067b9190612a01565b6111c5565b005b34801561068d575f80fd5b506106a860048036038101906106a39190612a2c565b6115c5565b6040516106b59190612836565b60405180910390f35b3480156106c9575f80fd5b506106d26115e5565b6040516106df91906129be565b60405180910390f35b3480156106f3575f80fd5b5061070e60048036038101906107099190612a01565b6115fd565b60405161071b9190612836565b60405180910390f35b34801561072f575f80fd5b50610738611612565b6040516107459190612836565b60405180910390f35b348015610759575f80fd5b50610774600480360381019061076f9190612a01565b611618565b6040516107819190612836565b60405180910390f35b348015610795575f80fd5b5061079e61162d565b005b3480156107ab575f80fd5b506107c660048036038101906107c19190612a01565b611710565b6040516107d39190612836565b60405180910390f35b3480156107e7575f80fd5b506107f0611725565b6040516107fd9190612936565b60405180910390f35b348015610811575f80fd5b5061081a6117b0565b6040516108279190612836565b60405180910390f35b34801561083b575f80fd5b506108446117b5565b005b348015610851575f80fd5b5061085a611a1f565b005b348015610867575f80fd5b50610882600480360381019061087d9190612a01565b611afa565b60405161088f9190612836565b60405180910390f35b3480156108a3575f80fd5b506108be60048036038101906108b99190612a01565b611b0f565b6040516108cb9190612836565b60405180910390f35b3480156108df575f80fd5b506108fa60048036038101906108f59190612a01565b611b24565b6040516109079190612836565b60405180910390f35b5f8273ffffffffffffffffffffffffffffffffffffffff16825f67ffffffffffffffff81111561094357610942612a6a565b5b6040519080825280601f01601f1916602001820160405280156109755781602001600182028036833780820191505090505b506040516109839190612b03565b5f6040518083038185875af1925050503d805f81146109bd576040519150601f19603f3d011682016040523d82523d5f602084013e6109c2565b606091505b5050905080610a06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109fd90612b99565b60405180910390fd5b505050565b60025481565b6060610a1d6004611b39565b905090565b600254341015610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612c01565b60405180910390fd5b6103e88110610aab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa290612c69565b60405180910390fd5b610abf336004611b5890919063ffffffff16565b15610aff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610af690612cd1565b60405180910390fd5b5f60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205414610b7e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7590612d39565b60405180910390fd5b610b92336004611b8590919063ffffffff16565b508060065f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503460085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507feeda149c76076b34d4b9d8896c2f7efc0d33d1c7b53ea3c5db490d64613f603a33604051610c4691906129be565b60405180910390a150565b600d8181548110610c60575f80fd5b905f5260205f20015f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600c5481565b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015610d6e57505f81115b610dad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da490612da1565b60405180910390fd5b610db73383611bb2565b8060095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610e0391906127ad565b92505081905550600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9055600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905560105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9055610f333382610910565b7fb698e31a2abee5824d0d7bcfd2339aead7f9e9ae413fba50bf554ff3fa470b7b338383604051610f6693929190612dbf565b60405180910390a15050565b600e602052805f5260405f205f915090505481565b6008602052805f5260405f205f915090505481565b60035481565b5f60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205411801561104357506003546002610ff891906126dc565b60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054611040919061277a565b43115b611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107990612e3e565b60405180910390fd5b5f60085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905060085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905560075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905561114d3382610910565b7f142e26dcca50281d2c46d90446bfc1c9bc260cef355ce917a52f1fec7c54b5bf338260405161117e929190612e5c565b60405180910390a150565b670de0b6b3a764000081565b600a602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015434101561120a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120190612c01565b60405180910390fd5b61121e816004611b5890919063ffffffff16565b61125d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161125490612ecd565b60405180910390fd5b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061132257505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611361576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135890612f35565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146113a35761139e3382611bb2565b61149e565b81600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600e5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505b34600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546114ea919061277a565b925050819055503460095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461153d919061277a565b925050819055504360105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc3383346040516115b993929190612dbf565b60405180910390a15050565b6011602052815f5260405f20602052805f5260405f205f91509150505481565b73121200000000000000000000000000000000000381565b600f602052805f5260405f205f915090505481565b60015481565b6006602052805f5260405f205f915090505481565b611641336004611b5890919063ffffffff16565b611680576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161167790612f9d565b60405180910390fd5b611694336004611e5d90919063ffffffff16565b504360075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507f7c79e6e24ed041d1072d54523b53956f01b91b835f0490856370594d9d14470e3360405161170691906129be565b60405180910390a1565b6010602052805f5260405f205f915090505481565b6060600d8054806020026020016040519081016040528092919081815260200182805480156117a657602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161175d575b5050505050905090565b5f5481565b73fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611837576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161182e90613005565b60405180910390fd5b600354600c54611847919061277a565b4310611a1d5773121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156118a6575f80fd5b505af11580156118b8573d5f803e3d5ffd5b505050505f6118c76004611b39565b90505f815190505f5b818110156119bc57600e5f8483815181106118ee576118ed612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205460115f85848151811061194657611945612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f600354600c54611998919061274a565b81526020019081526020015f208190555080806119b4906127e0565b9150506118d0565b5043600c819055506119cc611e8a565b600d90805190602001906119e19291906125d7565b507fe59e3b36b5c97b419925b60c92f5a4324c993934eb9cfe5232def67c1739337c600d604051611a129190613103565b60405180910390a150505b565b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611aed576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ae49061316d565b60405180910390fd5b611af73382611bb2565b50565b6009602052805f5260405f205f915090505481565b6007602052805f5260405f205f915090505481565b600b602052805f5260405f205f915090505481565b60605f611b47835f01612067565b905060608190508092505050919050565b5f611b7d835f018373ffffffffffffffffffffffffffffffffffffffff165f1b6120c0565b905092915050565b5f611baa835f018373ffffffffffffffffffffffffffffffffffffffff165f1b6120e0565b905092915050565b73121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611c0b575f80fd5b505af1158015611c1d573d5f803e3d5ffd5b505050505f60105f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f600f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f600e5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f60115f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6001600354600188611d3591906127ad565b611d3f919061274a565b611d49919061277a565b81526020019081526020015f2054905082811115611d65578092505b5f670de0b6b3a76400008484611d7b91906127ad565b600b5f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054611dc391906126dc565b611dcd919061274a565b905082600f5f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550611e1b8782610910565b7fbeceb521ccd2816457290c3d1cb70cc1537f14307f2d9ac26a5093a38ea409488782604051611e4c929190612e5c565b60405180910390a150505050505050565b5f611e82835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612147565b905092915050565b60605f611e95610a11565b90505f815190505f8167ffffffffffffffff811115611eb757611eb6612a6a565b5b604051908082528060200260200182016040528015611ee55781602001602082028036833780820191505090505b5090505f5b82811015611f7c5760095f858381518110611f0857611f07612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054828281518110611f5d57611f5c612679565b5b6020026020010181815250508080611f74906127e0565b915050611eea565b50611f8983825f54612243565b5f805467ffffffffffffffff811115611fa557611fa4612a6a565b5b604051908082528060200260200182016040528015611fd35781602001602082028036833780820191505090505b5090505f5b5f5481101561205c57848181518110611ff457611ff3612679565b5b602002602001015182828151811061200f5761200e612679565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080612054906127e0565b915050611fd8565b508094505050505090565b6060815f018054806020026020016040519081016040528092919081815260200182805480156120b457602002820191905f5260205f20905b8154815260200190600101908083116120a0575b50505050509050919050565b5f80836001015f8481526020019081526020015f20541415905092915050565b5f6120eb83836120c0565b61213d57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f208190555060019050612141565b5f90505b92915050565b5f80836001015f8481526020019081526020015f205490505f8114612238575f60018261217491906127ad565b90505f6001865f018054905061218a91906127ad565b90508082146121f0575f865f0182815481106121a9576121a8612679565b5b905f5260205f200154905080875f0184815481106121ca576121c9612679565b5b905f5260205f20018190555083876001015f8381526020019081526020015f2081905550505b855f018054806122035761220261318b565b5b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f90556001935050505061223d565b5f9150505b92915050565b5f835190505f600160028461225891906131c1565b6122629190613229565b90505b5f811261228b576122788585838661239e565b808061228390613269565b915050612265565b505f8290505b8181101561239757835f815181106122ac576122ab612679565b5b60200260200101518482815181106122c7576122c6612679565b5b60200260200101511115612384578381815181106122e8576122e7612679565b5b6020026020010151845f8151811061230357612302612679565b5b60200260200101818152505084818151811061232257612321612679565b5b6020026020010151855f8151811061233d5761233c612679565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061238385855f8661239e565b5b808061238f906127e0565b915050612291565b5050505050565b5f60018360026123ae91906126dc565b6123b8919061277a565b90505b818110156125d057816001826123d1919061277a565b10801561241d5750836001826123e7919061277a565b815181106123f8576123f7612679565b5b602002602001015184828151811061241357612412612679565b5b6020026020010151115b156124325760018161242f919061277a565b90505b83838151811061244557612444612679565b5b60200260200101518482815181106124605761245f612679565b5b6020026020010151116125d0578383815181106124805761247f612679565b5b602002602001015184828151811061249b5761249a612679565b5b60200260200101518583815181106124b6576124b5612679565b5b602002602001018686815181106124d0576124cf612679565b5b60200260200101828152508281525050508483815181106124f4576124f3612679565b5b602002602001015185828151811061250f5761250e612679565b5b602002602001015186838151811061252a57612529612679565b5b6020026020010187868151811061254457612543612679565b5b602002602001018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250505080925060016002826125bf91906126dc565b6125c9919061277a565b90506123bb565b5050505050565b828054828255905f5260205f2090810192821561264d579160200282015b8281111561264c578251825f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906125f5565b5b50905061265a919061265e565b5090565b5b80821115612675575f815f90555060010161265f565b5090565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6126e6826126a6565b91506126f1836126a6565b92508282026126ff816126a6565b91508282048414831517612716576127156126af565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612754826126a6565b915061275f836126a6565b92508261276f5761276e61271d565b5b828204905092915050565b5f612784826126a6565b915061278f836126a6565b92508282019050808211156127a7576127a66126af565b5b92915050565b5f6127b7826126a6565b91506127c2836126a6565b92508282039050818111156127da576127d96126af565b5b92915050565b5f6127ea826126a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361281c5761281b6126af565b5b600182019050919050565b612830816126a6565b82525050565b5f6020820190506128495f830184612827565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6128a182612878565b9050919050565b6128b181612897565b82525050565b5f6128c283836128a8565b60208301905092915050565b5f602082019050919050565b5f6128e48261284f565b6128ee8185612859565b93506128f983612869565b805f5b8381101561292957815161291088826128b7565b975061291b836128ce565b9250506001810190506128fc565b5085935050505092915050565b5f6020820190508181035f83015261294e81846128da565b905092915050565b5f80fd5b612963816126a6565b811461296d575f80fd5b50565b5f8135905061297e8161295a565b92915050565b5f6020828403121561299957612998612956565b5b5f6129a684828501612970565b91505092915050565b6129b881612897565b82525050565b5f6020820190506129d15f8301846129af565b92915050565b6129e081612897565b81146129ea575f80fd5b50565b5f813590506129fb816129d7565b92915050565b5f60208284031215612a1657612a15612956565b5b5f612a23848285016129ed565b91505092915050565b5f8060408385031215612a4257612a41612956565b5b5f612a4f858286016129ed565b9250506020612a6085828601612970565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f81519050919050565b5f81905092915050565b5f5b83811015612ac8578082015181840152602081019050612aad565b5f8484015250505050565b5f612add82612a97565b612ae78185612aa1565b9350612af7818560208601612aab565b80840191505092915050565b5f612b0e8284612ad3565b915081905092915050565b5f82825260208201905092915050565b7f736166655472616e736665724554483a20455448207472616e736665722066615f8201527f696c656400000000000000000000000000000000000000000000000000000000602082015250565b5f612b83602483612b19565b9150612b8e82612b29565b604082019050919050565b5f6020820190508181035f830152612bb081612b77565b9050919050565b7f696e73756666696369656e7420616d6f756e74000000000000000000000000005f82015250565b5f612beb601383612b19565b9150612bf682612bb7565b602082019050919050565b5f6020820190508181035f830152612c1881612bdf565b9050919050565b7f696e76616c6964207261746500000000000000000000000000000000000000005f82015250565b5f612c53600c83612b19565b9150612c5e82612c1f565b602082019050919050565b5f6020820190508181035f830152612c8081612c47565b9050919050565b7f63616e64696461746520657869737473000000000000000000000000000000005f82015250565b5f612cbb601083612b19565b9150612cc682612c87565b602082019050919050565b5f6020820190508181035f830152612ce881612caf565b9050919050565b7f6c656674206e6f7420636c61696d6564000000000000000000000000000000005f82015250565b5f612d23601083612b19565b9150612d2e82612cef565b602082019050919050565b5f6020820190508181035f830152612d5081612d17565b9050919050565b7f7265766f6b65206e6f7420616c6c6f77656400000000000000000000000000005f82015250565b5f612d8b601283612b19565b9150612d9682612d57565b602082019050919050565b5f6020820190508181035f830152612db881612d7f565b9050919050565b5f606082019050612dd25f8301866129af565b612ddf60208301856129af565b612dec6040830184612827565b949350505050565b7f7769746864726177206e6f7420616c6c6f7765640000000000000000000000005f82015250565b5f612e28601483612b19565b9150612e3382612df4565b602082019050919050565b5f6020820190508181035f830152612e5581612e1c565b9050919050565b5f604082019050612e6f5f8301856129af565b612e7c6020830184612827565b9392505050565b7f63616e646964617465206e6f7420616c6c6f77656400000000000000000000005f82015250565b5f612eb7601583612b19565b9150612ec282612e83565b602082019050919050565b5f6020820190508181035f830152612ee481612eab565b9050919050565b7f6f6e6c79206f6e652063686f69636520697320616c6c6f7765640000000000005f82015250565b5f612f1f601a83612b19565b9150612f2a82612eeb565b602082019050919050565b5f6020820190508181035f830152612f4c81612f13565b9050919050565b7f63616e646964617465206e6f74206578697374730000000000000000000000005f82015250565b5f612f87601483612b19565b9150612f9282612f53565b602082019050919050565b5f6020820190508181035f830152612fb481612f7b565b9050919050565b7f736964652063616c6c206e6f7420616c6c6f77656400000000000000000000005f82015250565b5f612fef601583612b19565b9150612ffa82612fbb565b602082019050919050565b5f6020820190508181035f83015261301c81612fe3565b9050919050565b5f81549050919050565b5f819050815f5260205f209050919050565b5f815f1c9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61307b6130768361303f565b61304a565b9050919050565b5f61308d8254613069565b9050919050565b5f600182019050919050565b5f6130aa82613023565b6130b48185612859565b93506130bf8361302d565b805f5b838110156130f6576130d382613082565b6130dd88826128b7565b97506130e883613094565b9250506001810190506130c2565b5085935050505092915050565b5f6020820190508181035f83015261311b81846130a0565b905092915050565b7f636c61696d206e6f7420616c6c6f7765640000000000000000000000000000005f82015250565b5f613157601183612b19565b915061316282613123565b602082019050919050565b5f6020820190508181035f8301526131848161314b565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f819050919050565b5f6131cb826131b8565b91506131d6836131b8565b9250826131e6576131e561271d565b5b60015f0383147f80000000000000000000000000000000000000000000000000000000000000008314161561321e5761321d6126af565b5b828205905092915050565b5f613233826131b8565b915061323e836131b8565b925082820390508181125f8412168282135f851215161715613263576132626126af565b5b92915050565b5f613273826131b8565b91507f800000000000000000000000000000000000000000000000000000000000000082036132a5576132a46126af565b5b60018203905091905056fea26469706673582212208754f76bcef83fcbb689a0e1dc0402efe99293e1de0da2d989454aeaaecf362864736f6c63430008140033" }, "0x1212100000000000000000000000000000000002": { "balance": "0", From c8ce78d9376c4c2ff176f72fd4d82c481781aea1 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Sat, 23 Mar 2024 00:09:49 +0800 Subject: [PATCH 55/66] fix genesis file --- genesis.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/genesis.json b/genesis.json index 2cbbf7c5cf..64745ce9e3 100644 --- a/genesis.json +++ b/genesis.json @@ -71,7 +71,7 @@ }, "0x1212100000000000000000000000000000000001": { "balance": "0", - "code": "0x60806040526004361061019f575f3560e01c8063786255f1116100eb5780639f9d7f8111610089578063b88a802f11610063578063b88a802f14610846578063d8ce95ab1461085c578063da0b331714610898578063db069ba5146108d457610458565b80639f9d7f81146107dc578063a6580de814610806578063a681dfec1461083057610458565b80638f1b3219116100c55780638f1b321914610724578063902bdc261461074e5780639690293b1461078a57806398ca58df146107a057610458565b8063786255f11461068257806389dc5c84146106be5780638e1900a8146106e857610458565b80634c569c2511610158578063611905331161013257806361190533146105ea578063683dd191146106005780636db504e71461062a5780636dd7d8ea1461066657610458565b80634c569c25146105485780634d21e426146105845780634ff0876a146105c057610458565b806303f187ea1461045c57806306a49fce146104865780630b2a85ea146104b05780630ea6a041146104cc5780631f26f2561461050857806343c14b221461053257610458565b36610458575f600d80548060200260200160405190810160405280929190818152602001828054801561022457602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116101db575b505050505090505f815190505f5b818110156104565760095f8483815181106102505761024f612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e85f54670de0b6b3a764000060065f8887815181106102b6576102b5612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20543461030391906126dc565b61030d91906126dc565b610317919061274a565b610321919061274a565b61032b919061274a565b600e5f85848151811061034157610340612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610390919061277a565b925050819055506104438382815181106103ad576103ac612679565b5b60200260200101516103e85f5460065f8887815181106103d0576103cf612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e861041f91906127ad565b3461042a91906126dc565b610434919061274a565b61043e919061274a565b610910565b808061044e906127e0565b915050610232565b005b5f80fd5b348015610467575f80fd5b50610470610a0b565b60405161047d9190612836565b60405180910390f35b348015610491575f80fd5b5061049a610a11565b6040516104a79190612936565b60405180910390f35b6104ca60048036038101906104c59190612984565b610a22565b005b3480156104d7575f80fd5b506104f260048036038101906104ed9190612984565b610c51565b6040516104ff91906129be565b60405180910390f35b348015610513575f80fd5b5061051c610c8c565b6040516105299190612836565b60405180910390f35b34801561053d575f80fd5b50610546610c92565b005b348015610553575f80fd5b5061056e60048036038101906105699190612a01565b610f72565b60405161057b9190612836565b60405180910390f35b34801561058f575f80fd5b506105aa60048036038101906105a59190612a01565b610f87565b6040516105b79190612836565b60405180910390f35b3480156105cb575f80fd5b506105d4610f9c565b6040516105e19190612836565b60405180910390f35b3480156105f5575f80fd5b506105fe610fa2565b005b34801561060b575f80fd5b50610614611189565b6040516106219190612836565b60405180910390f35b348015610635575f80fd5b50610650600480360381019061064b9190612a01565b611195565b60405161065d91906129be565b60405180910390f35b610680600480360381019061067b9190612a01565b6111c5565b005b34801561068d575f80fd5b506106a860048036038101906106a39190612a2c565b6115c5565b6040516106b59190612836565b60405180910390f35b3480156106c9575f80fd5b506106d26115e5565b6040516106df91906129be565b60405180910390f35b3480156106f3575f80fd5b5061070e60048036038101906107099190612a01565b6115fd565b60405161071b9190612836565b60405180910390f35b34801561072f575f80fd5b50610738611612565b6040516107459190612836565b60405180910390f35b348015610759575f80fd5b50610774600480360381019061076f9190612a01565b611618565b6040516107819190612836565b60405180910390f35b348015610795575f80fd5b5061079e61162d565b005b3480156107ab575f80fd5b506107c660048036038101906107c19190612a01565b611710565b6040516107d39190612836565b60405180910390f35b3480156107e7575f80fd5b506107f0611725565b6040516107fd9190612936565b60405180910390f35b348015610811575f80fd5b5061081a6117b0565b6040516108279190612836565b60405180910390f35b34801561083b575f80fd5b506108446117b5565b005b348015610851575f80fd5b5061085a611a1f565b005b348015610867575f80fd5b50610882600480360381019061087d9190612a01565b611afa565b60405161088f9190612836565b60405180910390f35b3480156108a3575f80fd5b506108be60048036038101906108b99190612a01565b611b0f565b6040516108cb9190612836565b60405180910390f35b3480156108df575f80fd5b506108fa60048036038101906108f59190612a01565b611b24565b6040516109079190612836565b60405180910390f35b5f8273ffffffffffffffffffffffffffffffffffffffff16825f67ffffffffffffffff81111561094357610942612a6a565b5b6040519080825280601f01601f1916602001820160405280156109755781602001600182028036833780820191505090505b506040516109839190612b03565b5f6040518083038185875af1925050503d805f81146109bd576040519150601f19603f3d011682016040523d82523d5f602084013e6109c2565b606091505b5050905080610a06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109fd90612b99565b60405180910390fd5b505050565b60025481565b6060610a1d6004611b39565b905090565b600254341015610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612c01565b60405180910390fd5b6103e88110610aab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa290612c69565b60405180910390fd5b610abf336004611b5890919063ffffffff16565b15610aff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610af690612cd1565b60405180910390fd5b5f60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205414610b7e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7590612d39565b60405180910390fd5b610b92336004611b8590919063ffffffff16565b508060065f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503460085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507feeda149c76076b34d4b9d8896c2f7efc0d33d1c7b53ea3c5db490d64613f603a33604051610c4691906129be565b60405180910390a150565b600d8181548110610c60575f80fd5b905f5260205f20015f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600c5481565b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015610d6e57505f81115b610dad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da490612da1565b60405180910390fd5b610db73383611bb2565b8060095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610e0391906127ad565b92505081905550600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9055600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905560105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9055610f333382610910565b7fb698e31a2abee5824d0d7bcfd2339aead7f9e9ae413fba50bf554ff3fa470b7b338383604051610f6693929190612dbf565b60405180910390a15050565b600e602052805f5260405f205f915090505481565b6008602052805f5260405f205f915090505481565b60035481565b5f60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205411801561104357506003546002610ff891906126dc565b60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054611040919061277a565b43115b611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107990612e3e565b60405180910390fd5b5f60085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905060085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905560075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905561114d3382610910565b7f142e26dcca50281d2c46d90446bfc1c9bc260cef355ce917a52f1fec7c54b5bf338260405161117e929190612e5c565b60405180910390a150565b670de0b6b3a764000081565b600a602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015434101561120a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120190612c01565b60405180910390fd5b61121e816004611b5890919063ffffffff16565b61125d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161125490612ecd565b60405180910390fd5b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061132257505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611361576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135890612f35565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146113a35761139e3382611bb2565b61149e565b81600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600e5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505b34600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546114ea919061277a565b925050819055503460095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461153d919061277a565b925050819055504360105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc3383346040516115b993929190612dbf565b60405180910390a15050565b6011602052815f5260405f20602052805f5260405f205f91509150505481565b73121200000000000000000000000000000000000381565b600f602052805f5260405f205f915090505481565b60015481565b6006602052805f5260405f205f915090505481565b611641336004611b5890919063ffffffff16565b611680576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161167790612f9d565b60405180910390fd5b611694336004611e5d90919063ffffffff16565b504360075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507f7c79e6e24ed041d1072d54523b53956f01b91b835f0490856370594d9d14470e3360405161170691906129be565b60405180910390a1565b6010602052805f5260405f205f915090505481565b6060600d8054806020026020016040519081016040528092919081815260200182805480156117a657602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161175d575b5050505050905090565b5f5481565b73fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611837576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161182e90613005565b60405180910390fd5b600354600c54611847919061277a565b4310611a1d5773121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156118a6575f80fd5b505af11580156118b8573d5f803e3d5ffd5b505050505f6118c76004611b39565b90505f815190505f5b818110156119bc57600e5f8483815181106118ee576118ed612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205460115f85848151811061194657611945612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f600354600c54611998919061274a565b81526020019081526020015f208190555080806119b4906127e0565b9150506118d0565b5043600c819055506119cc611e8a565b600d90805190602001906119e19291906125d7565b507fe59e3b36b5c97b419925b60c92f5a4324c993934eb9cfe5232def67c1739337c600d604051611a129190613103565b60405180910390a150505b565b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611aed576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ae49061316d565b60405180910390fd5b611af73382611bb2565b50565b6009602052805f5260405f205f915090505481565b6007602052805f5260405f205f915090505481565b600b602052805f5260405f205f915090505481565b60605f611b47835f01612067565b905060608190508092505050919050565b5f611b7d835f018373ffffffffffffffffffffffffffffffffffffffff165f1b6120c0565b905092915050565b5f611baa835f018373ffffffffffffffffffffffffffffffffffffffff165f1b6120e0565b905092915050565b73121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611c0b575f80fd5b505af1158015611c1d573d5f803e3d5ffd5b505050505f60105f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f600f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f600e5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f60115f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6001600354600188611d3591906127ad565b611d3f919061274a565b611d49919061277a565b81526020019081526020015f2054905082811115611d65578092505b5f670de0b6b3a76400008484611d7b91906127ad565b600b5f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054611dc391906126dc565b611dcd919061274a565b905082600f5f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550611e1b8782610910565b7fbeceb521ccd2816457290c3d1cb70cc1537f14307f2d9ac26a5093a38ea409488782604051611e4c929190612e5c565b60405180910390a150505050505050565b5f611e82835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612147565b905092915050565b60605f611e95610a11565b90505f815190505f8167ffffffffffffffff811115611eb757611eb6612a6a565b5b604051908082528060200260200182016040528015611ee55781602001602082028036833780820191505090505b5090505f5b82811015611f7c5760095f858381518110611f0857611f07612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054828281518110611f5d57611f5c612679565b5b6020026020010181815250508080611f74906127e0565b915050611eea565b50611f8983825f54612243565b5f805467ffffffffffffffff811115611fa557611fa4612a6a565b5b604051908082528060200260200182016040528015611fd35781602001602082028036833780820191505090505b5090505f5b5f5481101561205c57848181518110611ff457611ff3612679565b5b602002602001015182828151811061200f5761200e612679565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080612054906127e0565b915050611fd8565b508094505050505090565b6060815f018054806020026020016040519081016040528092919081815260200182805480156120b457602002820191905f5260205f20905b8154815260200190600101908083116120a0575b50505050509050919050565b5f80836001015f8481526020019081526020015f20541415905092915050565b5f6120eb83836120c0565b61213d57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f208190555060019050612141565b5f90505b92915050565b5f80836001015f8481526020019081526020015f205490505f8114612238575f60018261217491906127ad565b90505f6001865f018054905061218a91906127ad565b90508082146121f0575f865f0182815481106121a9576121a8612679565b5b905f5260205f200154905080875f0184815481106121ca576121c9612679565b5b905f5260205f20018190555083876001015f8381526020019081526020015f2081905550505b855f018054806122035761220261318b565b5b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f90556001935050505061223d565b5f9150505b92915050565b5f835190505f600160028461225891906131c1565b6122629190613229565b90505b5f811261228b576122788585838661239e565b808061228390613269565b915050612265565b505f8290505b8181101561239757835f815181106122ac576122ab612679565b5b60200260200101518482815181106122c7576122c6612679565b5b60200260200101511115612384578381815181106122e8576122e7612679565b5b6020026020010151845f8151811061230357612302612679565b5b60200260200101818152505084818151811061232257612321612679565b5b6020026020010151855f8151811061233d5761233c612679565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061238385855f8661239e565b5b808061238f906127e0565b915050612291565b5050505050565b5f60018360026123ae91906126dc565b6123b8919061277a565b90505b818110156125d057816001826123d1919061277a565b10801561241d5750836001826123e7919061277a565b815181106123f8576123f7612679565b5b602002602001015184828151811061241357612412612679565b5b6020026020010151115b156124325760018161242f919061277a565b90505b83838151811061244557612444612679565b5b60200260200101518482815181106124605761245f612679565b5b6020026020010151116125d0578383815181106124805761247f612679565b5b602002602001015184828151811061249b5761249a612679565b5b60200260200101518583815181106124b6576124b5612679565b5b602002602001018686815181106124d0576124cf612679565b5b60200260200101828152508281525050508483815181106124f4576124f3612679565b5b602002602001015185828151811061250f5761250e612679565b5b602002602001015186838151811061252a57612529612679565b5b6020026020010187868151811061254457612543612679565b5b602002602001018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250505080925060016002826125bf91906126dc565b6125c9919061277a565b90506123bb565b5050505050565b828054828255905f5260205f2090810192821561264d579160200282015b8281111561264c578251825f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906125f5565b5b50905061265a919061265e565b5090565b5b80821115612675575f815f90555060010161265f565b5090565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6126e6826126a6565b91506126f1836126a6565b92508282026126ff816126a6565b91508282048414831517612716576127156126af565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612754826126a6565b915061275f836126a6565b92508261276f5761276e61271d565b5b828204905092915050565b5f612784826126a6565b915061278f836126a6565b92508282019050808211156127a7576127a66126af565b5b92915050565b5f6127b7826126a6565b91506127c2836126a6565b92508282039050818111156127da576127d96126af565b5b92915050565b5f6127ea826126a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361281c5761281b6126af565b5b600182019050919050565b612830816126a6565b82525050565b5f6020820190506128495f830184612827565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6128a182612878565b9050919050565b6128b181612897565b82525050565b5f6128c283836128a8565b60208301905092915050565b5f602082019050919050565b5f6128e48261284f565b6128ee8185612859565b93506128f983612869565b805f5b8381101561292957815161291088826128b7565b975061291b836128ce565b9250506001810190506128fc565b5085935050505092915050565b5f6020820190508181035f83015261294e81846128da565b905092915050565b5f80fd5b612963816126a6565b811461296d575f80fd5b50565b5f8135905061297e8161295a565b92915050565b5f6020828403121561299957612998612956565b5b5f6129a684828501612970565b91505092915050565b6129b881612897565b82525050565b5f6020820190506129d15f8301846129af565b92915050565b6129e081612897565b81146129ea575f80fd5b50565b5f813590506129fb816129d7565b92915050565b5f60208284031215612a1657612a15612956565b5b5f612a23848285016129ed565b91505092915050565b5f8060408385031215612a4257612a41612956565b5b5f612a4f858286016129ed565b9250506020612a6085828601612970565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f81519050919050565b5f81905092915050565b5f5b83811015612ac8578082015181840152602081019050612aad565b5f8484015250505050565b5f612add82612a97565b612ae78185612aa1565b9350612af7818560208601612aab565b80840191505092915050565b5f612b0e8284612ad3565b915081905092915050565b5f82825260208201905092915050565b7f736166655472616e736665724554483a20455448207472616e736665722066615f8201527f696c656400000000000000000000000000000000000000000000000000000000602082015250565b5f612b83602483612b19565b9150612b8e82612b29565b604082019050919050565b5f6020820190508181035f830152612bb081612b77565b9050919050565b7f696e73756666696369656e7420616d6f756e74000000000000000000000000005f82015250565b5f612beb601383612b19565b9150612bf682612bb7565b602082019050919050565b5f6020820190508181035f830152612c1881612bdf565b9050919050565b7f696e76616c6964207261746500000000000000000000000000000000000000005f82015250565b5f612c53600c83612b19565b9150612c5e82612c1f565b602082019050919050565b5f6020820190508181035f830152612c8081612c47565b9050919050565b7f63616e64696461746520657869737473000000000000000000000000000000005f82015250565b5f612cbb601083612b19565b9150612cc682612c87565b602082019050919050565b5f6020820190508181035f830152612ce881612caf565b9050919050565b7f6c656674206e6f7420636c61696d6564000000000000000000000000000000005f82015250565b5f612d23601083612b19565b9150612d2e82612cef565b602082019050919050565b5f6020820190508181035f830152612d5081612d17565b9050919050565b7f7265766f6b65206e6f7420616c6c6f77656400000000000000000000000000005f82015250565b5f612d8b601283612b19565b9150612d9682612d57565b602082019050919050565b5f6020820190508181035f830152612db881612d7f565b9050919050565b5f606082019050612dd25f8301866129af565b612ddf60208301856129af565b612dec6040830184612827565b949350505050565b7f7769746864726177206e6f7420616c6c6f7765640000000000000000000000005f82015250565b5f612e28601483612b19565b9150612e3382612df4565b602082019050919050565b5f6020820190508181035f830152612e5581612e1c565b9050919050565b5f604082019050612e6f5f8301856129af565b612e7c6020830184612827565b9392505050565b7f63616e646964617465206e6f7420616c6c6f77656400000000000000000000005f82015250565b5f612eb7601583612b19565b9150612ec282612e83565b602082019050919050565b5f6020820190508181035f830152612ee481612eab565b9050919050565b7f6f6e6c79206f6e652063686f69636520697320616c6c6f7765640000000000005f82015250565b5f612f1f601a83612b19565b9150612f2a82612eeb565b602082019050919050565b5f6020820190508181035f830152612f4c81612f13565b9050919050565b7f63616e646964617465206e6f74206578697374730000000000000000000000005f82015250565b5f612f87601483612b19565b9150612f9282612f53565b602082019050919050565b5f6020820190508181035f830152612fb481612f7b565b9050919050565b7f736964652063616c6c206e6f7420616c6c6f77656400000000000000000000005f82015250565b5f612fef601583612b19565b9150612ffa82612fbb565b602082019050919050565b5f6020820190508181035f83015261301c81612fe3565b9050919050565b5f81549050919050565b5f819050815f5260205f209050919050565b5f815f1c9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61307b6130768361303f565b61304a565b9050919050565b5f61308d8254613069565b9050919050565b5f600182019050919050565b5f6130aa82613023565b6130b48185612859565b93506130bf8361302d565b805f5b838110156130f6576130d382613082565b6130dd88826128b7565b97506130e883613094565b9250506001810190506130c2565b5085935050505092915050565b5f6020820190508181035f83015261311b81846130a0565b905092915050565b7f636c61696d206e6f7420616c6c6f7765640000000000000000000000000000005f82015250565b5f613157601183612b19565b915061316282613123565b602082019050919050565b5f6020820190508181035f8301526131848161314b565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f819050919050565b5f6131cb826131b8565b91506131d6836131b8565b9250826131e6576131e561271d565b5b60015f0383147f80000000000000000000000000000000000000000000000000000000000000008314161561321e5761321d6126af565b5b828205905092915050565b5f613233826131b8565b915061323e836131b8565b925082820390508181125f8412168282135f851215161715613263576132626126af565b5b92915050565b5f613273826131b8565b91507f800000000000000000000000000000000000000000000000000000000000000082036132a5576132a46126af565b5b60018203905091905056fea26469706673582212208754f76bcef83fcbb689a0e1dc0402efe99293e1de0da2d989454aeaaecf362864736f6c63430008140033" + "code": "0x60806040526004361061019f575f3560e01c8063786255f1116100eb5780639f9d7f8111610089578063b88a802f11610063578063b88a802f14610846578063d8ce95ab1461085c578063da0b331714610898578063db069ba5146108d457610458565b80639f9d7f81146107dc578063a6580de814610806578063a681dfec1461083057610458565b80638f1b3219116100c55780638f1b321914610724578063902bdc261461074e5780639690293b1461078a57806398ca58df146107a057610458565b8063786255f11461068257806389dc5c84146106be5780638e1900a8146106e857610458565b80634c569c2511610158578063611905331161013257806361190533146105ea578063683dd191146106005780636db504e71461062a5780636dd7d8ea1461066657610458565b80634c569c25146105485780634d21e426146105845780634ff0876a146105c057610458565b806303f187ea1461045c57806306a49fce146104865780630b2a85ea146104b05780630ea6a041146104cc5780631f26f2561461050857806343c14b221461053257610458565b36610458575f600d80548060200260200160405190810160405280929190818152602001828054801561022457602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116101db575b505050505090505f815190505f5b818110156104565760095f8483815181106102505761024f612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e85f54670de0b6b3a764000060065f8887815181106102b6576102b5612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20543461030391906126dc565b61030d91906126dc565b610317919061274a565b610321919061274a565b61032b919061274a565b600e5f85848151811061034157610340612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610390919061277a565b925050819055506104438382815181106103ad576103ac612679565b5b60200260200101516103e85f5460065f8887815181106103d0576103cf612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e861041f91906127ad565b3461042a91906126dc565b610434919061274a565b61043e919061274a565b610910565b808061044e906127e0565b915050610232565b005b5f80fd5b348015610467575f80fd5b50610470610a0b565b60405161047d9190612836565b60405180910390f35b348015610491575f80fd5b5061049a610a11565b6040516104a79190612936565b60405180910390f35b6104ca60048036038101906104c59190612984565b610a22565b005b3480156104d7575f80fd5b506104f260048036038101906104ed9190612984565b610c51565b6040516104ff91906129be565b60405180910390f35b348015610513575f80fd5b5061051c610c8c565b6040516105299190612836565b60405180910390f35b34801561053d575f80fd5b50610546610c92565b005b348015610553575f80fd5b5061056e60048036038101906105699190612a01565b610f72565b60405161057b9190612836565b60405180910390f35b34801561058f575f80fd5b506105aa60048036038101906105a59190612a01565b610f87565b6040516105b79190612836565b60405180910390f35b3480156105cb575f80fd5b506105d4610f9c565b6040516105e19190612836565b60405180910390f35b3480156105f5575f80fd5b506105fe610fa2565b005b34801561060b575f80fd5b50610614611189565b6040516106219190612836565b60405180910390f35b348015610635575f80fd5b50610650600480360381019061064b9190612a01565b611195565b60405161065d91906129be565b60405180910390f35b610680600480360381019061067b9190612a01565b6111c5565b005b34801561068d575f80fd5b506106a860048036038101906106a39190612a2c565b6115c5565b6040516106b59190612836565b60405180910390f35b3480156106c9575f80fd5b506106d26115e5565b6040516106df91906129be565b60405180910390f35b3480156106f3575f80fd5b5061070e60048036038101906107099190612a01565b6115fd565b60405161071b9190612836565b60405180910390f35b34801561072f575f80fd5b50610738611612565b6040516107459190612836565b60405180910390f35b348015610759575f80fd5b50610774600480360381019061076f9190612a01565b611618565b6040516107819190612836565b60405180910390f35b348015610795575f80fd5b5061079e61162d565b005b3480156107ab575f80fd5b506107c660048036038101906107c19190612a01565b611710565b6040516107d39190612836565b60405180910390f35b3480156107e7575f80fd5b506107f0611725565b6040516107fd9190612936565b60405180910390f35b348015610811575f80fd5b5061081a6117b0565b6040516108279190612836565b60405180910390f35b34801561083b575f80fd5b506108446117b5565b005b348015610851575f80fd5b5061085a611a1f565b005b348015610867575f80fd5b50610882600480360381019061087d9190612a01565b611afa565b60405161088f9190612836565b60405180910390f35b3480156108a3575f80fd5b506108be60048036038101906108b99190612a01565b611b0f565b6040516108cb9190612836565b60405180910390f35b3480156108df575f80fd5b506108fa60048036038101906108f59190612a01565b611b24565b6040516109079190612836565b60405180910390f35b5f8273ffffffffffffffffffffffffffffffffffffffff16825f67ffffffffffffffff81111561094357610942612a6a565b5b6040519080825280601f01601f1916602001820160405280156109755781602001600182028036833780820191505090505b506040516109839190612b03565b5f6040518083038185875af1925050503d805f81146109bd576040519150601f19603f3d011682016040523d82523d5f602084013e6109c2565b606091505b5050905080610a06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109fd90612b99565b60405180910390fd5b505050565b60025481565b6060610a1d6004611b39565b905090565b600254341015610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612c01565b60405180910390fd5b6103e88110610aab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa290612c69565b60405180910390fd5b610abf336004611b5890919063ffffffff16565b15610aff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610af690612cd1565b60405180910390fd5b5f60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205414610b7e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7590612d39565b60405180910390fd5b610b92336004611b8590919063ffffffff16565b508060065f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503460085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507feeda149c76076b34d4b9d8896c2f7efc0d33d1c7b53ea3c5db490d64613f603a33604051610c4691906129be565b60405180910390a150565b600d8181548110610c60575f80fd5b905f5260205f20015f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600c5481565b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015610d6e57505f81115b610dad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da490612da1565b60405180910390fd5b610db73383611bb2565b8060095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610e0391906127ad565b92505081905550600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9055600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905560105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9055610f333382610910565b7fb698e31a2abee5824d0d7bcfd2339aead7f9e9ae413fba50bf554ff3fa470b7b338383604051610f6693929190612dbf565b60405180910390a15050565b600e602052805f5260405f205f915090505481565b6008602052805f5260405f205f915090505481565b60035481565b5f60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205411801561104357506003546002610ff891906126dc565b60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054611040919061277a565b43115b611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107990612e3e565b60405180910390fd5b5f60085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905060085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905560075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905561114d3382610910565b7f142e26dcca50281d2c46d90446bfc1c9bc260cef355ce917a52f1fec7c54b5bf338260405161117e929190612e5c565b60405180910390a150565b670de0b6b3a764000081565b600a602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015434101561120a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120190612c01565b60405180910390fd5b61121e816004611b5890919063ffffffff16565b61125d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161125490612ecd565b60405180910390fd5b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061132257505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611361576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135890612f35565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146113a35761139e3382611bb2565b61149e565b81600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600e5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505b34600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546114ea919061277a565b925050819055503460095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461153d919061277a565b925050819055504360105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc3383346040516115b993929190612dbf565b60405180910390a15050565b6011602052815f5260405f20602052805f5260405f205f91509150505481565b73121200000000000000000000000000000000000381565b600f602052805f5260405f205f915090505481565b60015481565b6006602052805f5260405f205f915090505481565b611641336004611b5890919063ffffffff16565b611680576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161167790612f9d565b60405180910390fd5b611694336004611e5d90919063ffffffff16565b504360075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507f7c79e6e24ed041d1072d54523b53956f01b91b835f0490856370594d9d14470e3360405161170691906129be565b60405180910390a1565b6010602052805f5260405f205f915090505481565b6060600d8054806020026020016040519081016040528092919081815260200182805480156117a657602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161175d575b5050505050905090565b5f5481565b73fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611837576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161182e90613005565b60405180910390fd5b600354600c54611847919061277a565b4310611a1d5773121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156118a6575f80fd5b505af11580156118b8573d5f803e3d5ffd5b505050505f6118c76004611b39565b90505f815190505f5b818110156119bc57600e5f8483815181106118ee576118ed612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205460115f85848151811061194657611945612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f600354600c54611998919061274a565b81526020019081526020015f208190555080806119b4906127e0565b9150506118d0565b5043600c819055506119cc611e8a565b600d90805190602001906119e19291906125d7565b507fe59e3b36b5c97b419925b60c92f5a4324c993934eb9cfe5232def67c1739337c600d604051611a129190613103565b60405180910390a150505b565b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611aed576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ae49061316d565b60405180910390fd5b611af73382611bb2565b50565b6009602052805f5260405f205f915090505481565b6007602052805f5260405f205f915090505481565b600b602052805f5260405f205f915090505481565b60605f611b47835f01612067565b905060608190508092505050919050565b5f611b7d835f018373ffffffffffffffffffffffffffffffffffffffff165f1b6120c0565b905092915050565b5f611baa835f018373ffffffffffffffffffffffffffffffffffffffff165f1b6120e0565b905092915050565b73121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611c0b575f80fd5b505af1158015611c1d573d5f803e3d5ffd5b505050505f60105f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f600f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f600e5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f60115f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6001600354600188611d3591906127ad565b611d3f919061274a565b611d49919061277a565b81526020019081526020015f2054905082811115611d65578092505b5f670de0b6b3a76400008484611d7b91906127ad565b600b5f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054611dc391906126dc565b611dcd919061274a565b905082600f5f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550611e1b8782610910565b7fbeceb521ccd2816457290c3d1cb70cc1537f14307f2d9ac26a5093a38ea409488782604051611e4c929190612e5c565b60405180910390a150505050505050565b5f611e82835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612147565b905092915050565b60605f611e95610a11565b90505f815190505f8167ffffffffffffffff811115611eb757611eb6612a6a565b5b604051908082528060200260200182016040528015611ee55781602001602082028036833780820191505090505b5090505f5b82811015611f7c5760095f858381518110611f0857611f07612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054828281518110611f5d57611f5c612679565b5b6020026020010181815250508080611f74906127e0565b915050611eea565b50611f8983825f54612243565b5f805467ffffffffffffffff811115611fa557611fa4612a6a565b5b604051908082528060200260200182016040528015611fd35781602001602082028036833780820191505090505b5090505f5b5f5481101561205c57848181518110611ff457611ff3612679565b5b602002602001015182828151811061200f5761200e612679565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080612054906127e0565b915050611fd8565b508094505050505090565b6060815f018054806020026020016040519081016040528092919081815260200182805480156120b457602002820191905f5260205f20905b8154815260200190600101908083116120a0575b50505050509050919050565b5f80836001015f8481526020019081526020015f20541415905092915050565b5f6120eb83836120c0565b61213d57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f208190555060019050612141565b5f90505b92915050565b5f80836001015f8481526020019081526020015f205490505f8114612238575f60018261217491906127ad565b90505f6001865f018054905061218a91906127ad565b90508082146121f0575f865f0182815481106121a9576121a8612679565b5b905f5260205f200154905080875f0184815481106121ca576121c9612679565b5b905f5260205f20018190555083876001015f8381526020019081526020015f2081905550505b855f018054806122035761220261318b565b5b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f90556001935050505061223d565b5f9150505b92915050565b5f835190505f600160028461225891906131c1565b6122629190613229565b90505b5f811261228b576122788585838661239e565b808061228390613269565b915050612265565b505f8290505b8181101561239757835f815181106122ac576122ab612679565b5b60200260200101518482815181106122c7576122c6612679565b5b60200260200101511115612384578381815181106122e8576122e7612679565b5b6020026020010151845f8151811061230357612302612679565b5b60200260200101818152505084818151811061232257612321612679565b5b6020026020010151855f8151811061233d5761233c612679565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061238385855f8661239e565b5b808061238f906127e0565b915050612291565b5050505050565b5f60018360026123ae91906126dc565b6123b8919061277a565b90505b818110156125d057816001826123d1919061277a565b10801561241d5750836001826123e7919061277a565b815181106123f8576123f7612679565b5b602002602001015184828151811061241357612412612679565b5b6020026020010151115b156124325760018161242f919061277a565b90505b83838151811061244557612444612679565b5b60200260200101518482815181106124605761245f612679565b5b6020026020010151116125d0578383815181106124805761247f612679565b5b602002602001015184828151811061249b5761249a612679565b5b60200260200101518583815181106124b6576124b5612679565b5b602002602001018686815181106124d0576124cf612679565b5b60200260200101828152508281525050508483815181106124f4576124f3612679565b5b602002602001015185828151811061250f5761250e612679565b5b602002602001015186838151811061252a57612529612679565b5b6020026020010187868151811061254457612543612679565b5b602002602001018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250505080925060016002826125bf91906126dc565b6125c9919061277a565b90506123bb565b5050505050565b828054828255905f5260205f2090810192821561264d579160200282015b8281111561264c578251825f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906125f5565b5b50905061265a919061265e565b5090565b5b80821115612675575f815f90555060010161265f565b5090565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6126e6826126a6565b91506126f1836126a6565b92508282026126ff816126a6565b91508282048414831517612716576127156126af565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612754826126a6565b915061275f836126a6565b92508261276f5761276e61271d565b5b828204905092915050565b5f612784826126a6565b915061278f836126a6565b92508282019050808211156127a7576127a66126af565b5b92915050565b5f6127b7826126a6565b91506127c2836126a6565b92508282039050818111156127da576127d96126af565b5b92915050565b5f6127ea826126a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361281c5761281b6126af565b5b600182019050919050565b612830816126a6565b82525050565b5f6020820190506128495f830184612827565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6128a182612878565b9050919050565b6128b181612897565b82525050565b5f6128c283836128a8565b60208301905092915050565b5f602082019050919050565b5f6128e48261284f565b6128ee8185612859565b93506128f983612869565b805f5b8381101561292957815161291088826128b7565b975061291b836128ce565b9250506001810190506128fc565b5085935050505092915050565b5f6020820190508181035f83015261294e81846128da565b905092915050565b5f80fd5b612963816126a6565b811461296d575f80fd5b50565b5f8135905061297e8161295a565b92915050565b5f6020828403121561299957612998612956565b5b5f6129a684828501612970565b91505092915050565b6129b881612897565b82525050565b5f6020820190506129d15f8301846129af565b92915050565b6129e081612897565b81146129ea575f80fd5b50565b5f813590506129fb816129d7565b92915050565b5f60208284031215612a1657612a15612956565b5b5f612a23848285016129ed565b91505092915050565b5f8060408385031215612a4257612a41612956565b5b5f612a4f858286016129ed565b9250506020612a6085828601612970565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f81519050919050565b5f81905092915050565b5f5b83811015612ac8578082015181840152602081019050612aad565b5f8484015250505050565b5f612add82612a97565b612ae78185612aa1565b9350612af7818560208601612aab565b80840191505092915050565b5f612b0e8284612ad3565b915081905092915050565b5f82825260208201905092915050565b7f736166655472616e736665724554483a20455448207472616e736665722066615f8201527f696c656400000000000000000000000000000000000000000000000000000000602082015250565b5f612b83602483612b19565b9150612b8e82612b29565b604082019050919050565b5f6020820190508181035f830152612bb081612b77565b9050919050565b7f696e73756666696369656e7420616d6f756e74000000000000000000000000005f82015250565b5f612beb601383612b19565b9150612bf682612bb7565b602082019050919050565b5f6020820190508181035f830152612c1881612bdf565b9050919050565b7f696e76616c6964207261746500000000000000000000000000000000000000005f82015250565b5f612c53600c83612b19565b9150612c5e82612c1f565b602082019050919050565b5f6020820190508181035f830152612c8081612c47565b9050919050565b7f63616e64696461746520657869737473000000000000000000000000000000005f82015250565b5f612cbb601083612b19565b9150612cc682612c87565b602082019050919050565b5f6020820190508181035f830152612ce881612caf565b9050919050565b7f6c656674206e6f7420636c61696d6564000000000000000000000000000000005f82015250565b5f612d23601083612b19565b9150612d2e82612cef565b602082019050919050565b5f6020820190508181035f830152612d5081612d17565b9050919050565b7f7265766f6b65206e6f7420616c6c6f77656400000000000000000000000000005f82015250565b5f612d8b601283612b19565b9150612d9682612d57565b602082019050919050565b5f6020820190508181035f830152612db881612d7f565b9050919050565b5f606082019050612dd25f8301866129af565b612ddf60208301856129af565b612dec6040830184612827565b949350505050565b7f7769746864726177206e6f7420616c6c6f7765640000000000000000000000005f82015250565b5f612e28601483612b19565b9150612e3382612df4565b602082019050919050565b5f6020820190508181035f830152612e5581612e1c565b9050919050565b5f604082019050612e6f5f8301856129af565b612e7c6020830184612827565b9392505050565b7f63616e646964617465206e6f7420616c6c6f77656400000000000000000000005f82015250565b5f612eb7601583612b19565b9150612ec282612e83565b602082019050919050565b5f6020820190508181035f830152612ee481612eab565b9050919050565b7f6f6e6c79206f6e652063686f69636520697320616c6c6f7765640000000000005f82015250565b5f612f1f601a83612b19565b9150612f2a82612eeb565b602082019050919050565b5f6020820190508181035f830152612f4c81612f13565b9050919050565b7f63616e646964617465206e6f74206578697374730000000000000000000000005f82015250565b5f612f87601483612b19565b9150612f9282612f53565b602082019050919050565b5f6020820190508181035f830152612fb481612f7b565b9050919050565b7f736964652063616c6c206e6f7420616c6c6f77656400000000000000000000005f82015250565b5f612fef601583612b19565b9150612ffa82612fbb565b602082019050919050565b5f6020820190508181035f83015261301c81612fe3565b9050919050565b5f81549050919050565b5f819050815f5260205f209050919050565b5f815f1c9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61307b6130768361303f565b61304a565b9050919050565b5f61308d8254613069565b9050919050565b5f600182019050919050565b5f6130aa82613023565b6130b48185612859565b93506130bf8361302d565b805f5b838110156130f6576130d382613082565b6130dd88826128b7565b97506130e883613094565b9250506001810190506130c2565b5085935050505092915050565b5f6020820190508181035f83015261311b81846130a0565b905092915050565b7f636c61696d206e6f7420616c6c6f7765640000000000000000000000000000005f82015250565b5f613157601183612b19565b915061316282613123565b602082019050919050565b5f6020820190508181035f8301526131848161314b565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f819050919050565b5f6131cb826131b8565b91506131d6836131b8565b9250826131e6576131e561271d565b5b60015f0383147f80000000000000000000000000000000000000000000000000000000000000008314161561321e5761321d6126af565b5b828205905092915050565b5f613233826131b8565b915061323e836131b8565b925082820390508181125f8412168282135f851215161715613263576132626126af565b5b92915050565b5f613273826131b8565b91507f800000000000000000000000000000000000000000000000000000000000000082036132a5576132a46126af565b5b60018203905091905056fea264697066735822122042a4a23e321855e52345a33a8ad5f0f5715323b6c775917f25daeb28a38bef3464736f6c63430008140033" }, "0x1212100000000000000000000000000000000002": { "balance": "0", From ecbe0f75e8337f9b74b5d3431553de5d6ab5dd80 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Sat, 23 Mar 2024 12:57:57 +0800 Subject: [PATCH 56/66] add access limit to receive() --- contracts/solidity/GovernanceV2.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index ecd3cf81bd..daab43017d 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -47,6 +47,8 @@ contract GovernanceV2 is IGovernanceV2 { // GovReward contract address public constant govReward = 0x1212000000000000000000000000000000000003; + address public constant sysCall = + 0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE; uint public constant scaleFactor = 10 ** 18; uint public consensusSize; @@ -88,6 +90,7 @@ contract GovernanceV2 is IGovernanceV2 { mapping(address => mapping(uint => uint)) public epochStartGasPerVote; receive() external payable { + require(msg.sender == govReward, "side call not allowed"); address[] memory validators = currentConsensus; uint length = validators.length; for (uint i = 0; i < length; i++) { @@ -205,7 +208,7 @@ contract GovernanceV2 is IGovernanceV2 { } function onPersist() external { - require(msg.sender == address(0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE), "side call not allowed"); + require(msg.sender == sysCall, "side call not allowed"); if (block.number < currentEpochStartHeight + epochDuration) { return; } From e25388d658c7287b1305fb17688f573e91e2b47b Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Sat, 23 Mar 2024 21:30:16 +0800 Subject: [PATCH 57/66] fix withdrawRegisterFee --- contracts/solidity/GovernanceV2.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index daab43017d..94183f736e 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -146,6 +146,7 @@ contract GovernanceV2 is IGovernanceV2 { uint amount = candidateBalanceOf[msg.sender]; delete candidateBalanceOf[msg.sender]; delete exitHeightOf[msg.sender]; + delete shareRateOf[msg.sender]; _safeTransferETH(msg.sender, amount); emit CandidateWithdraw(msg.sender, amount); } From 456f01cc906a6955116b12334ab668f6c5177c77 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Sat, 23 Mar 2024 21:37:03 +0800 Subject: [PATCH 58/66] add balance check before gov reward transfer --- contracts/solidity/GovRewardV2.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/solidity/GovRewardV2.sol b/contracts/solidity/GovRewardV2.sol index 3d863afda5..fd32447008 100644 --- a/contracts/solidity/GovRewardV2.sol +++ b/contracts/solidity/GovRewardV2.sol @@ -47,6 +47,8 @@ contract GovReward is IGovReward { } function withdraw() external onlyGov { - TransferHelper.safeTransferETH(governance, address(this).balance); + if (address(this).balance > 0) { + TransferHelper.safeTransferETH(governance, address(this).balance); + } } } From bca9d68ccb03cec78ad7d15c9707ee387dcb14ef Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Sat, 23 Mar 2024 21:54:29 +0800 Subject: [PATCH 59/66] update onPersist --- contracts/solidity/GovernanceV2.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 94183f736e..2360a8da77 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -135,7 +135,7 @@ contract GovernanceV2 is IGovernanceV2 { function withdrawRegisterFee() external { // require 2 epochs to exit candidate list - // NOTE: suppose onPersist always happens in time + // NOTE: suppose epoch change always happens in time require( exitHeightOf[msg.sender] > 0 && block.number > exitHeightOf[msg.sender] + 2 * epochDuration, @@ -209,13 +209,15 @@ contract GovernanceV2 is IGovernanceV2 { } function onPersist() external { + // NOTE: suppose onPersist always happens at the beginning of every block require(msg.sender == sysCall, "side call not allowed"); + // only settle validator reward if there is no epoch change + IGovReward(govReward).withdraw(); if (block.number < currentEpochStartHeight + epochDuration) { return; } // update tag values - IGovReward(govReward).withdraw(); address[] memory candidates = candidateList.values(); uint length = candidates.length; for (uint i = 0; i < length; i++) { @@ -235,14 +237,12 @@ contract GovernanceV2 is IGovernanceV2 { } function _settleReward(address voter, address candidate) internal { - IGovReward(govReward).withdraw(); - + // NOTE: suppose onPersist always happens at the beginning of every block, then latestGasPerVote is always the latest uint height = voteHeight[voter]; uint lastGasPerVote = voterGasPerVote[voter]; uint latestGasPerVote = candidateGasPerVote[candidate]; - // NOTE: suppose onPersist always happens in the correct block at expected height - // NOTE: suppose onPersist always happens at the beginning of a block, then vote in that block should wait another epoch to farm reward + // NOTE: suppose epoch change always happens at the beginning of a block, then vote in that block should wait another epoch to farm reward uint voteEpochEndGasPerVote = epochStartGasPerVote[candidate][ (height - 1) / epochDuration + 1 ]; From 1ac730438e81a328c9668cdaeb1d84d03af8c212 Mon Sep 17 00:00:00 2001 From: Hu Shili <799498265@qq.com> Date: Sat, 23 Mar 2024 22:10:16 +0800 Subject: [PATCH 60/66] make vote() user-friendly Co-authored-by: Anna Shaleva --- contracts/solidity/GovernanceV2.sol | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 2360a8da77..ba5c66003b 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -172,8 +172,10 @@ contract GovernanceV2 is IGovernanceV2 { // update votes votedAmount[msg.sender] += msg.value; receivedVotes[candidateTo] += msg.value; - // NOTE: the left reward in current epoch will be unclaimable - voteHeight[msg.sender] = block.number; + // NOTE: the left reward in the epoch of first vote will be unclaimable. + if (votedCandidate == address(0)) { + voteHeight[msg.sender] = block.number; + } emit Vote(msg.sender, candidateTo, msg.value); } From 9ee869be387933927b0ff8e985b9b49754b0e37d Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Sat, 23 Mar 2024 22:26:32 +0800 Subject: [PATCH 61/66] update genesis file --- genesis.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/genesis.json b/genesis.json index 64745ce9e3..caa4e22979 100644 --- a/genesis.json +++ b/genesis.json @@ -71,7 +71,7 @@ }, "0x1212100000000000000000000000000000000001": { "balance": "0", - "code": "0x60806040526004361061019f575f3560e01c8063786255f1116100eb5780639f9d7f8111610089578063b88a802f11610063578063b88a802f14610846578063d8ce95ab1461085c578063da0b331714610898578063db069ba5146108d457610458565b80639f9d7f81146107dc578063a6580de814610806578063a681dfec1461083057610458565b80638f1b3219116100c55780638f1b321914610724578063902bdc261461074e5780639690293b1461078a57806398ca58df146107a057610458565b8063786255f11461068257806389dc5c84146106be5780638e1900a8146106e857610458565b80634c569c2511610158578063611905331161013257806361190533146105ea578063683dd191146106005780636db504e71461062a5780636dd7d8ea1461066657610458565b80634c569c25146105485780634d21e426146105845780634ff0876a146105c057610458565b806303f187ea1461045c57806306a49fce146104865780630b2a85ea146104b05780630ea6a041146104cc5780631f26f2561461050857806343c14b221461053257610458565b36610458575f600d80548060200260200160405190810160405280929190818152602001828054801561022457602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116101db575b505050505090505f815190505f5b818110156104565760095f8483815181106102505761024f612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e85f54670de0b6b3a764000060065f8887815181106102b6576102b5612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20543461030391906126dc565b61030d91906126dc565b610317919061274a565b610321919061274a565b61032b919061274a565b600e5f85848151811061034157610340612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610390919061277a565b925050819055506104438382815181106103ad576103ac612679565b5b60200260200101516103e85f5460065f8887815181106103d0576103cf612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e861041f91906127ad565b3461042a91906126dc565b610434919061274a565b61043e919061274a565b610910565b808061044e906127e0565b915050610232565b005b5f80fd5b348015610467575f80fd5b50610470610a0b565b60405161047d9190612836565b60405180910390f35b348015610491575f80fd5b5061049a610a11565b6040516104a79190612936565b60405180910390f35b6104ca60048036038101906104c59190612984565b610a22565b005b3480156104d7575f80fd5b506104f260048036038101906104ed9190612984565b610c51565b6040516104ff91906129be565b60405180910390f35b348015610513575f80fd5b5061051c610c8c565b6040516105299190612836565b60405180910390f35b34801561053d575f80fd5b50610546610c92565b005b348015610553575f80fd5b5061056e60048036038101906105699190612a01565b610f72565b60405161057b9190612836565b60405180910390f35b34801561058f575f80fd5b506105aa60048036038101906105a59190612a01565b610f87565b6040516105b79190612836565b60405180910390f35b3480156105cb575f80fd5b506105d4610f9c565b6040516105e19190612836565b60405180910390f35b3480156105f5575f80fd5b506105fe610fa2565b005b34801561060b575f80fd5b50610614611189565b6040516106219190612836565b60405180910390f35b348015610635575f80fd5b50610650600480360381019061064b9190612a01565b611195565b60405161065d91906129be565b60405180910390f35b610680600480360381019061067b9190612a01565b6111c5565b005b34801561068d575f80fd5b506106a860048036038101906106a39190612a2c565b6115c5565b6040516106b59190612836565b60405180910390f35b3480156106c9575f80fd5b506106d26115e5565b6040516106df91906129be565b60405180910390f35b3480156106f3575f80fd5b5061070e60048036038101906107099190612a01565b6115fd565b60405161071b9190612836565b60405180910390f35b34801561072f575f80fd5b50610738611612565b6040516107459190612836565b60405180910390f35b348015610759575f80fd5b50610774600480360381019061076f9190612a01565b611618565b6040516107819190612836565b60405180910390f35b348015610795575f80fd5b5061079e61162d565b005b3480156107ab575f80fd5b506107c660048036038101906107c19190612a01565b611710565b6040516107d39190612836565b60405180910390f35b3480156107e7575f80fd5b506107f0611725565b6040516107fd9190612936565b60405180910390f35b348015610811575f80fd5b5061081a6117b0565b6040516108279190612836565b60405180910390f35b34801561083b575f80fd5b506108446117b5565b005b348015610851575f80fd5b5061085a611a1f565b005b348015610867575f80fd5b50610882600480360381019061087d9190612a01565b611afa565b60405161088f9190612836565b60405180910390f35b3480156108a3575f80fd5b506108be60048036038101906108b99190612a01565b611b0f565b6040516108cb9190612836565b60405180910390f35b3480156108df575f80fd5b506108fa60048036038101906108f59190612a01565b611b24565b6040516109079190612836565b60405180910390f35b5f8273ffffffffffffffffffffffffffffffffffffffff16825f67ffffffffffffffff81111561094357610942612a6a565b5b6040519080825280601f01601f1916602001820160405280156109755781602001600182028036833780820191505090505b506040516109839190612b03565b5f6040518083038185875af1925050503d805f81146109bd576040519150601f19603f3d011682016040523d82523d5f602084013e6109c2565b606091505b5050905080610a06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109fd90612b99565b60405180910390fd5b505050565b60025481565b6060610a1d6004611b39565b905090565b600254341015610a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a5e90612c01565b60405180910390fd5b6103e88110610aab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa290612c69565b60405180910390fd5b610abf336004611b5890919063ffffffff16565b15610aff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610af690612cd1565b60405180910390fd5b5f60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205414610b7e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b7590612d39565b60405180910390fd5b610b92336004611b8590919063ffffffff16565b508060065f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503460085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507feeda149c76076b34d4b9d8896c2f7efc0d33d1c7b53ea3c5db490d64613f603a33604051610c4691906129be565b60405180910390a150565b600d8181548110610c60575f80fd5b905f5260205f20015f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600c5481565b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015610d6e57505f81115b610dad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da490612da1565b60405180910390fd5b610db73383611bb2565b8060095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610e0391906127ad565b92505081905550600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9055600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905560105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9055610f333382610910565b7fb698e31a2abee5824d0d7bcfd2339aead7f9e9ae413fba50bf554ff3fa470b7b338383604051610f6693929190612dbf565b60405180910390a15050565b600e602052805f5260405f205f915090505481565b6008602052805f5260405f205f915090505481565b60035481565b5f60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205411801561104357506003546002610ff891906126dc565b60075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054611040919061277a565b43115b611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107990612e3e565b60405180910390fd5b5f60085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905060085f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905560075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f905561114d3382610910565b7f142e26dcca50281d2c46d90446bfc1c9bc260cef355ce917a52f1fec7c54b5bf338260405161117e929190612e5c565b60405180910390a150565b670de0b6b3a764000081565b600a602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60015434101561120a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120190612c01565b60405180910390fd5b61121e816004611b5890919063ffffffff16565b61125d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161125490612ecd565b60405180910390fd5b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061132257505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b611361576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135890612f35565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146113a35761139e3382611bb2565b61149e565b81600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600e5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054600f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505b34600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546114ea919061277a565b925050819055503460095f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461153d919061277a565b925050819055504360105f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc3383346040516115b993929190612dbf565b60405180910390a15050565b6011602052815f5260405f20602052805f5260405f205f91509150505481565b73121200000000000000000000000000000000000381565b600f602052805f5260405f205f915090505481565b60015481565b6006602052805f5260405f205f915090505481565b611641336004611b5890919063ffffffff16565b611680576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161167790612f9d565b60405180910390fd5b611694336004611e5d90919063ffffffff16565b504360075f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055507f7c79e6e24ed041d1072d54523b53956f01b91b835f0490856370594d9d14470e3360405161170691906129be565b60405180910390a1565b6010602052805f5260405f205f915090505481565b6060600d8054806020026020016040519081016040528092919081815260200182805480156117a657602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161175d575b5050505050905090565b5f5481565b73fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611837576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161182e90613005565b60405180910390fd5b600354600c54611847919061277a565b4310611a1d5773121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156118a6575f80fd5b505af11580156118b8573d5f803e3d5ffd5b505050505f6118c76004611b39565b90505f815190505f5b818110156119bc57600e5f8483815181106118ee576118ed612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205460115f85848151811061194657611945612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f600354600c54611998919061274a565b81526020019081526020015f208190555080806119b4906127e0565b9150506118d0565b5043600c819055506119cc611e8a565b600d90805190602001906119e19291906125d7565b507fe59e3b36b5c97b419925b60c92f5a4324c993934eb9cfe5232def67c1739337c600d604051611a129190613103565b60405180910390a150505b565b5f600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611aed576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ae49061316d565b60405180910390fd5b611af73382611bb2565b50565b6009602052805f5260405f205f915090505481565b6007602052805f5260405f205f915090505481565b600b602052805f5260405f205f915090505481565b60605f611b47835f01612067565b905060608190508092505050919050565b5f611b7d835f018373ffffffffffffffffffffffffffffffffffffffff165f1b6120c0565b905092915050565b5f611baa835f018373ffffffffffffffffffffffffffffffffffffffff165f1b6120e0565b905092915050565b73121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611c0b575f80fd5b505af1158015611c1d573d5f803e3d5ffd5b505050505f60105f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f600f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f600e5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490505f60115f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6001600354600188611d3591906127ad565b611d3f919061274a565b611d49919061277a565b81526020019081526020015f2054905082811115611d65578092505b5f670de0b6b3a76400008484611d7b91906127ad565b600b5f8a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054611dc391906126dc565b611dcd919061274a565b905082600f5f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550611e1b8782610910565b7fbeceb521ccd2816457290c3d1cb70cc1537f14307f2d9ac26a5093a38ea409488782604051611e4c929190612e5c565b60405180910390a150505050505050565b5f611e82835f018373ffffffffffffffffffffffffffffffffffffffff165f1b612147565b905092915050565b60605f611e95610a11565b90505f815190505f8167ffffffffffffffff811115611eb757611eb6612a6a565b5b604051908082528060200260200182016040528015611ee55781602001602082028036833780820191505090505b5090505f5b82811015611f7c5760095f858381518110611f0857611f07612679565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054828281518110611f5d57611f5c612679565b5b6020026020010181815250508080611f74906127e0565b915050611eea565b50611f8983825f54612243565b5f805467ffffffffffffffff811115611fa557611fa4612a6a565b5b604051908082528060200260200182016040528015611fd35781602001602082028036833780820191505090505b5090505f5b5f5481101561205c57848181518110611ff457611ff3612679565b5b602002602001015182828151811061200f5761200e612679565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080612054906127e0565b915050611fd8565b508094505050505090565b6060815f018054806020026020016040519081016040528092919081815260200182805480156120b457602002820191905f5260205f20905b8154815260200190600101908083116120a0575b50505050509050919050565b5f80836001015f8481526020019081526020015f20541415905092915050565b5f6120eb83836120c0565b61213d57825f0182908060018154018082558091505060019003905f5260205f20015f9091909190915055825f0180549050836001015f8481526020019081526020015f208190555060019050612141565b5f90505b92915050565b5f80836001015f8481526020019081526020015f205490505f8114612238575f60018261217491906127ad565b90505f6001865f018054905061218a91906127ad565b90508082146121f0575f865f0182815481106121a9576121a8612679565b5b905f5260205f200154905080875f0184815481106121ca576121c9612679565b5b905f5260205f20018190555083876001015f8381526020019081526020015f2081905550505b855f018054806122035761220261318b565b5b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f90556001935050505061223d565b5f9150505b92915050565b5f835190505f600160028461225891906131c1565b6122629190613229565b90505b5f811261228b576122788585838661239e565b808061228390613269565b915050612265565b505f8290505b8181101561239757835f815181106122ac576122ab612679565b5b60200260200101518482815181106122c7576122c6612679565b5b60200260200101511115612384578381815181106122e8576122e7612679565b5b6020026020010151845f8151811061230357612302612679565b5b60200260200101818152505084818151811061232257612321612679565b5b6020026020010151855f8151811061233d5761233c612679565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505061238385855f8661239e565b5b808061238f906127e0565b915050612291565b5050505050565b5f60018360026123ae91906126dc565b6123b8919061277a565b90505b818110156125d057816001826123d1919061277a565b10801561241d5750836001826123e7919061277a565b815181106123f8576123f7612679565b5b602002602001015184828151811061241357612412612679565b5b6020026020010151115b156124325760018161242f919061277a565b90505b83838151811061244557612444612679565b5b60200260200101518482815181106124605761245f612679565b5b6020026020010151116125d0578383815181106124805761247f612679565b5b602002602001015184828151811061249b5761249a612679565b5b60200260200101518583815181106124b6576124b5612679565b5b602002602001018686815181106124d0576124cf612679565b5b60200260200101828152508281525050508483815181106124f4576124f3612679565b5b602002602001015185828151811061250f5761250e612679565b5b602002602001015186838151811061252a57612529612679565b5b6020026020010187868151811061254457612543612679565b5b602002602001018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152508273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250505080925060016002826125bf91906126dc565b6125c9919061277a565b90506123bb565b5050505050565b828054828255905f5260205f2090810192821561264d579160200282015b8281111561264c578251825f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906125f5565b5b50905061265a919061265e565b5090565b5b80821115612675575f815f90555060010161265f565b5090565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6126e6826126a6565b91506126f1836126a6565b92508282026126ff816126a6565b91508282048414831517612716576127156126af565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612754826126a6565b915061275f836126a6565b92508261276f5761276e61271d565b5b828204905092915050565b5f612784826126a6565b915061278f836126a6565b92508282019050808211156127a7576127a66126af565b5b92915050565b5f6127b7826126a6565b91506127c2836126a6565b92508282039050818111156127da576127d96126af565b5b92915050565b5f6127ea826126a6565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361281c5761281b6126af565b5b600182019050919050565b612830816126a6565b82525050565b5f6020820190506128495f830184612827565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6128a182612878565b9050919050565b6128b181612897565b82525050565b5f6128c283836128a8565b60208301905092915050565b5f602082019050919050565b5f6128e48261284f565b6128ee8185612859565b93506128f983612869565b805f5b8381101561292957815161291088826128b7565b975061291b836128ce565b9250506001810190506128fc565b5085935050505092915050565b5f6020820190508181035f83015261294e81846128da565b905092915050565b5f80fd5b612963816126a6565b811461296d575f80fd5b50565b5f8135905061297e8161295a565b92915050565b5f6020828403121561299957612998612956565b5b5f6129a684828501612970565b91505092915050565b6129b881612897565b82525050565b5f6020820190506129d15f8301846129af565b92915050565b6129e081612897565b81146129ea575f80fd5b50565b5f813590506129fb816129d7565b92915050565b5f60208284031215612a1657612a15612956565b5b5f612a23848285016129ed565b91505092915050565b5f8060408385031215612a4257612a41612956565b5b5f612a4f858286016129ed565b9250506020612a6085828601612970565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f81519050919050565b5f81905092915050565b5f5b83811015612ac8578082015181840152602081019050612aad565b5f8484015250505050565b5f612add82612a97565b612ae78185612aa1565b9350612af7818560208601612aab565b80840191505092915050565b5f612b0e8284612ad3565b915081905092915050565b5f82825260208201905092915050565b7f736166655472616e736665724554483a20455448207472616e736665722066615f8201527f696c656400000000000000000000000000000000000000000000000000000000602082015250565b5f612b83602483612b19565b9150612b8e82612b29565b604082019050919050565b5f6020820190508181035f830152612bb081612b77565b9050919050565b7f696e73756666696369656e7420616d6f756e74000000000000000000000000005f82015250565b5f612beb601383612b19565b9150612bf682612bb7565b602082019050919050565b5f6020820190508181035f830152612c1881612bdf565b9050919050565b7f696e76616c6964207261746500000000000000000000000000000000000000005f82015250565b5f612c53600c83612b19565b9150612c5e82612c1f565b602082019050919050565b5f6020820190508181035f830152612c8081612c47565b9050919050565b7f63616e64696461746520657869737473000000000000000000000000000000005f82015250565b5f612cbb601083612b19565b9150612cc682612c87565b602082019050919050565b5f6020820190508181035f830152612ce881612caf565b9050919050565b7f6c656674206e6f7420636c61696d6564000000000000000000000000000000005f82015250565b5f612d23601083612b19565b9150612d2e82612cef565b602082019050919050565b5f6020820190508181035f830152612d5081612d17565b9050919050565b7f7265766f6b65206e6f7420616c6c6f77656400000000000000000000000000005f82015250565b5f612d8b601283612b19565b9150612d9682612d57565b602082019050919050565b5f6020820190508181035f830152612db881612d7f565b9050919050565b5f606082019050612dd25f8301866129af565b612ddf60208301856129af565b612dec6040830184612827565b949350505050565b7f7769746864726177206e6f7420616c6c6f7765640000000000000000000000005f82015250565b5f612e28601483612b19565b9150612e3382612df4565b602082019050919050565b5f6020820190508181035f830152612e5581612e1c565b9050919050565b5f604082019050612e6f5f8301856129af565b612e7c6020830184612827565b9392505050565b7f63616e646964617465206e6f7420616c6c6f77656400000000000000000000005f82015250565b5f612eb7601583612b19565b9150612ec282612e83565b602082019050919050565b5f6020820190508181035f830152612ee481612eab565b9050919050565b7f6f6e6c79206f6e652063686f69636520697320616c6c6f7765640000000000005f82015250565b5f612f1f601a83612b19565b9150612f2a82612eeb565b602082019050919050565b5f6020820190508181035f830152612f4c81612f13565b9050919050565b7f63616e646964617465206e6f74206578697374730000000000000000000000005f82015250565b5f612f87601483612b19565b9150612f9282612f53565b602082019050919050565b5f6020820190508181035f830152612fb481612f7b565b9050919050565b7f736964652063616c6c206e6f7420616c6c6f77656400000000000000000000005f82015250565b5f612fef601583612b19565b9150612ffa82612fbb565b602082019050919050565b5f6020820190508181035f83015261301c81612fe3565b9050919050565b5f81549050919050565b5f819050815f5260205f209050919050565b5f815f1c9050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61307b6130768361303f565b61304a565b9050919050565b5f61308d8254613069565b9050919050565b5f600182019050919050565b5f6130aa82613023565b6130b48185612859565b93506130bf8361302d565b805f5b838110156130f6576130d382613082565b6130dd88826128b7565b97506130e883613094565b9250506001810190506130c2565b5085935050505092915050565b5f6020820190508181035f83015261311b81846130a0565b905092915050565b7f636c61696d206e6f7420616c6c6f7765640000000000000000000000000000005f82015250565b5f613157601183612b19565b915061316282613123565b602082019050919050565b5f6020820190508181035f8301526131848161314b565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f819050919050565b5f6131cb826131b8565b91506131d6836131b8565b9250826131e6576131e561271d565b5b60015f0383147f80000000000000000000000000000000000000000000000000000000000000008314161561321e5761321d6126af565b5b828205905092915050565b5f613233826131b8565b915061323e836131b8565b925082820390508181125f8412168282135f851215161715613263576132626126af565b5b92915050565b5f613273826131b8565b91507f800000000000000000000000000000000000000000000000000000000000000082036132a5576132a46126af565b5b60018203905091905056fea264697066735822122042a4a23e321855e52345a33a8ad5f0f5715323b6c775917f25daeb28a38bef3464736f6c63430008140033" + "code": "0x6080604052600436106101b2575f3560e01c806389dc5c84116100e75780639f9d7f8111610087578063b88a802f11610062578063b88a802f1461070c578063d8ce95ab14610720578063da0b33171461074b578063db069ba514610776575f80fd5b80639f9d7f81146106d0578063a6580de8146106e4578063a681dfec146106f8575f80fd5b8063902bdc26116100c2578063902bdc261461064c5780639690293b1461067757806398ca58df1461068b5780639e40cdac146106b6575f80fd5b806389dc5c84146105f15780638e1900a81461060c5780638f1b321914610637575f80fd5b80634d21e42611610152578063683dd1911161012d578063683dd191146105595780636db504e7146105745780636dd7d8ea146105a8578063786255f1146105bb575f80fd5b80634d21e426146105055780634ff0876a146105305780636119053314610545575f80fd5b80630ea6a0411161018d5780630ea6a0411461047a5780631f26f256146104b157806343c14b22146104c65780634c569c25146104da575f80fd5b806303f187ea1461041e57806306a49fce146104465780630b2a85ea14610467575f80fd5b3661041a5733600361090960911b011461020b5760405162461bcd60e51b81526020600482015260156024820152741cda59194818d85b1b081b9bdd08185b1b1bddd959605a1b60448201526064015b60405180910390fd5b5f600d80548060200260200160405190810160405280929190818152602001828054801561026057602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610242575b505083519394505f925050505b818110156104185760095f84838151811061028a5761028a6119b1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20546103e85f54670de0b6b3a764000060065f8887815181106102d5576102d56119b1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20543461030891906119d9565b61031291906119d9565b61031c9190611a04565b6103269190611a04565b6103309190611a04565b600e5f858481518110610345576103456119b1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f205f82825461037a9190611a17565b92505081905550610410838281518110610396576103966119b1565b60200260200101516103e85f5460065f8887815181106103b8576103b86119b1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20546103e86103ed9190611a2a565b6103f790346119d9565b6104019190611a04565b61040b9190611a04565b6107a1565b60010161026d565b005b5f80fd5b348015610429575f80fd5b5061043360025481565b6040519081526020015b60405180910390f35b348015610451575f80fd5b5061045a61086b565b60405161043d9190611a3d565b610418610475366004611a89565b61087c565b348015610485575f80fd5b50610499610494366004611a89565b6109fd565b6040516001600160a01b03909116815260200161043d565b3480156104bc575f80fd5b50610433600c5481565b3480156104d1575f80fd5b50610418610a25565b3480156104e5575f80fd5b506104336104f4366004611abb565b600e6020525f908152604090205481565b348015610510575f80fd5b5061043361051f366004611abb565b60086020525f908152604090205481565b34801561053b575f80fd5b5061043360035481565b348015610550575f80fd5b50610418610b64565b348015610564575f80fd5b50610433670de0b6b3a764000081565b34801561057f575f80fd5b5061049961058e366004611abb565b600a6020525f90815260409020546001600160a01b031681565b6104186105b6366004611abb565b610c56565b3480156105c6575f80fd5b506104336105d5366004611ad4565b601160209081525f928352604080842090915290825290205481565b3480156105fc575f80fd5b50610499600361090960911b0181565b348015610617575f80fd5b50610433610626366004611abb565b600f6020525f908152604090205481565b348015610642575f80fd5b5061043360015481565b348015610657575f80fd5b50610433610666366004611abb565b60066020525f908152604090205481565b348015610682575f80fd5b50610418610e82565b348015610696575f80fd5b506104336106a5366004611abb565b60106020525f908152604090205481565b3480156106c1575f80fd5b506104996002600160a01b0381565b3480156106db575f80fd5b5061045a610f23565b3480156106ef575f80fd5b506104335f5481565b348015610703575f80fd5b50610418610f83565b348015610717575f80fd5b5061041861114e565b34801561072b575f80fd5b5061043361073a366004611abb565b60096020525f908152604090205481565b348015610756575f80fd5b50610433610765366004611abb565b60076020525f908152604090205481565b348015610781575f80fd5b50610433610790366004611abb565b600b6020525f908152604090205481565b604080515f808252602082019092526001600160a01b0384169083906040516107ca9190611b10565b5f6040518083038185875af1925050503d805f8114610804576040519150601f19603f3d011682016040523d82523d5f602084013e610809565b606091505b50509050806108665760405162461bcd60e51b8152602060048201526024808201527f736166655472616e736665724554483a20455448207472616e736665722066616044820152631a5b195960e21b6064820152608401610202565b505050565b606061087760046111b4565b905090565b6002543410156108c45760405162461bcd60e51b81526020600482015260136024820152721a5b9cdd59999a58da595b9d08185b5bdd5b9d606a1b6044820152606401610202565b6103e881106109045760405162461bcd60e51b815260206004820152600c60248201526b696e76616c6964207261746560a01b6044820152606401610202565b61090f6004336111c7565b1561094f5760405162461bcd60e51b815260206004820152601060248201526f63616e6469646174652065786973747360801b6044820152606401610202565b335f908152600760205260409020541561099e5760405162461bcd60e51b815260206004820152601060248201526f1b19599d081b9bdd0818db185a5b595960821b6044820152606401610202565b6109a96004336111ed565b50335f818152600660209081526040808320859055600882529182902034905590519182527feeda149c76076b34d4b9d8896c2f7efc0d33d1c7b53ea3c5db490d64613f603a91015b60405180910390a150565b600d8181548110610a0c575f80fd5b5f918252602090912001546001600160a01b0316905081565b335f908152600a6020908152604080832054600b909252909120546001600160a01b03909116908115801590610a5a57505f81115b610a9b5760405162461bcd60e51b81526020600482015260126024820152711c995d9bdad9481b9bdd08185b1b1bddd95960721b6044820152606401610202565b610aa53383611201565b6001600160a01b0382165f9081526009602052604081208054839290610acc908490611a2a565b9091555050335f818152600a6020908152604080832080546001600160a01b0319169055600b8252808320839055600f82528083208390556010909152812055610b1690826107a1565b604080513381526001600160a01b03841660208201529081018290527fb698e31a2abee5824d0d7bcfd2339aead7f9e9ae413fba50bf554ff3fa470b7b906060015b60405180910390a15050565b335f9081526007602052604090205415801590610ba65750600354610b8a9060026119d9565b335f90815260076020526040902054610ba39190611a17565b43115b610be95760405162461bcd60e51b81526020600482015260146024820152731dda5d1a191c985dc81b9bdd08185b1b1bddd95960621b6044820152606401610202565b335f81815260086020908152604080832080549084905560078352818420849055600690925282209190915590610c2090826107a1565b60408051338152602081018390527f142e26dcca50281d2c46d90446bfc1c9bc260cef355ce917a52f1fec7c54b5bf91016109f2565b600154341015610c9e5760405162461bcd60e51b81526020600482015260136024820152721a5b9cdd59999a58da595b9d08185b5bdd5b9d606a1b6044820152606401610202565b610ca96004826111c7565b610ced5760405162461bcd60e51b815260206004820152601560248201527418d85b991a59185d19481b9bdd08185b1b1bddd959605a1b6044820152606401610202565b335f908152600a60205260409020546001600160a01b03908116908216811480610d1e57506001600160a01b038116155b610d6a5760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c79206f6e652063686f69636520697320616c6c6f7765640000000000006044820152606401610202565b6001600160a01b03811615610d8857610d833382611201565b610dcb565b335f818152600a6020908152604080832080546001600160a01b0319166001600160a01b0388169081179091558352600e825280832054938352600f9091529020555b335f908152600b602052604081208054349290610de9908490611a17565b90915550506001600160a01b0382165f9081526009602052604081208054349290610e15908490611a17565b90915550506001600160a01b038116610e3a57335f9081526010602052604090204390555b604080513381526001600160a01b038416602082015234918101919091527f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc90606001610b58565b610e8d6004336111c7565b610ed05760405162461bcd60e51b815260206004820152601460248201527363616e646964617465206e6f742065786973747360601b6044820152606401610202565b610edb600433611330565b50335f8181526007602090815260409182902043905590519182527f7c79e6e24ed041d1072d54523b53956f01b91b835f0490856370594d9d14470e910160405180910390a1565b6060600d805480602002602001604051908101604052809291908181526020018280548015610f7957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610f5b575b5050505050905090565b336002600160a01b0314610fd15760405162461bcd60e51b81526020600482015260156024820152741cda59194818d85b1b081b9bdd08185b1b1bddd959605a1b6044820152606401610202565b600361090960911b016001600160a01b0316633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611011575f80fd5b505af1158015611023573d5f803e3d5ffd5b50505050600354600c546110379190611a17565b43101561104057565b5f61104b60046111b4565b80519091505f5b818110156110fc57600e5f84838151811061106f5761106f6119b1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f205460115f8584815181106110ac576110ac6119b1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f205f600354600c546110e49190611a04565b815260208101919091526040015f2055600101611052565b5043600c55611109611344565b805161111d91600d9160209091019061193a565b507fe59e3b36b5c97b419925b60c92f5a4324c993934eb9cfe5232def67c1739337c600d604051610b589190611b3c565b335f908152600a60205260409020546001600160a01b0316806111a75760405162461bcd60e51b815260206004820152601160248201527018db185a5b481b9bdd08185b1b1bddd959607a1b6044820152606401610202565b6111b13382611201565b50565b60605f6111c0836114ba565b9392505050565b6001600160a01b0381165f90815260018301602052604081205415155b90505b92915050565b5f6111e4836001600160a01b038416611513565b6001600160a01b038083165f90815260106020908152604080832054600f8352818420549486168452600e835281842054601190935290832060035491949391829061124e600188611a2a565b6112589190611a04565b611263906001611a17565b81526020019081526020015f205490508281111561127f578092505b5f670de0b6b3a76400006112938585611a2a565b6001600160a01b0389165f908152600b60205260409020546112b591906119d9565b6112bf9190611a04565b6001600160a01b0388165f908152600f6020526040902084905590506112e587826107a1565b604080516001600160a01b0389168152602081018390527fbeceb521ccd2816457290c3d1cb70cc1537f14307f2d9ac26a5093a38ea40948910160405180910390a150505050505050565b5f6111e4836001600160a01b03841661155f565b60605f61134f61086b565b80519091505f8167ffffffffffffffff81111561136e5761136e611afc565b604051908082528060200260200182016040528015611397578160200160208202803683370190505b5090505f5b828110156114065760095f8583815181106113b9576113b96119b1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20548282815181106113f3576113f36119b1565b602090810291909101015260010161139c565b5061141383825f54611649565b5f805467ffffffffffffffff81111561142e5761142e611afc565b604051908082528060200260200182016040528015611457578160200160208202803683370190505b5090505f5b5f548110156114b157848181518110611477576114776119b1565b6020026020010151828281518110611491576114916119b1565b6001600160a01b039092166020928302919091019091015260010161145c565b50949350505050565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561150757602002820191905f5260205f20905b8154815260200190600101908083116114f3575b50505050509050919050565b5f81815260018301602052604081205461155857508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556111e7565b505f6111e7565b5f8181526001830160205260408120548015611639575f611581600183611a2a565b85549091505f9061159490600190611a2a565b90508082146115f3575f865f0182815481106115b2576115b26119b1565b905f5260205f200154905080875f0184815481106115d2576115d26119b1565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061160457611604611b7f565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506111e7565b5f9150506111e7565b5092915050565b82515f6001611659600285611b93565b6116639190611bbf565b90505b5f811261168b576116798585838661176f565b8061168381611bde565b915050611666565b50815b8181101561176857835f815181106116a8576116a86119b1565b60200260200101518482815181106116c2576116c26119b1565b60200260200101511115611760578381815181106116e2576116e26119b1565b6020026020010151845f815181106116fc576116fc6119b1565b60200260200101818152505084818151811061171a5761171a6119b1565b6020026020010151855f81518110611734576117346119b1565b60200260200101906001600160a01b031690816001600160a01b03168152505061176085855f8661176f565b60010161168e565b5050505050565b5f61177b8360026119d9565b611786906001611a17565b90505b81811015611768578161179d826001611a17565b1080156117e55750836117b1826001611a17565b815181106117c1576117c16119b1565b60200260200101518482815181106117db576117db6119b1565b6020026020010151115b156117f8576117f5600182611a17565b90505b83838151811061180a5761180a6119b1565b6020026020010151848281518110611824576118246119b1565b60200260200101511161176857838381518110611843576118436119b1565b602002602001015184828151811061185d5761185d6119b1565b6020026020010151858381518110611877576118776119b1565b60200260200101868681518110611890576118906119b1565b60200260200101828152508281525050508483815181106118b3576118b36119b1565b60200260200101518582815181106118cd576118cd6119b1565b60200260200101518683815181106118e7576118e76119b1565b60200260200101878681518110611900576119006119b1565b6001600160a01b039384166020918202929092010152911690529150816119288160026119d9565b611933906001611a17565b9050611789565b828054828255905f5260205f2090810192821561198d579160200282015b8281111561198d57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190611958565b5061199992915061199d565b5090565b5b80821115611999575f815560010161199e565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176111e7576111e76119c5565b634e487b7160e01b5f52601260045260245ffd5b5f82611a1257611a126119f0565b500490565b808201808211156111e7576111e76119c5565b818103818111156111e7576111e76119c5565b602080825282518282018190525f9190848201906040850190845b81811015611a7d5783516001600160a01b031683529284019291840191600101611a58565b50909695505050505050565b5f60208284031215611a99575f80fd5b5035919050565b80356001600160a01b0381168114611ab6575f80fd5b919050565b5f60208284031215611acb575f80fd5b6111e482611aa0565b5f8060408385031215611ae5575f80fd5b611aee83611aa0565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b5f82515f5b81811015611b2f5760208186018101518583015201611b15565b505f920191825250919050565b602080825282548282018190525f8481528281209092916040850190845b81811015611a7d5783546001600160a01b031683526001938401939285019201611b5a565b634e487b7160e01b5f52603160045260245ffd5b5f82611ba157611ba16119f0565b600160ff1b82145f1984141615611bba57611bba6119c5565b500590565b8181035f831280158383131683831282161715611642576116426119c5565b5f600160ff1b8201611bf257611bf26119c5565b505f19019056fea26469706673582212202abe25305608726694348364ab10e4772662e4e71c0dff136f5af913f9daf21564736f6c63430008180033" }, "0x1212100000000000000000000000000000000002": { "balance": "0", From 281ad690badebc9ced08f7b27dd8483ed63f778d Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Sat, 23 Mar 2024 22:39:51 +0800 Subject: [PATCH 62/66] change optimize configuration --- genesis.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/genesis.json b/genesis.json index caa4e22979..2641b44e62 100644 --- a/genesis.json +++ b/genesis.json @@ -71,7 +71,7 @@ }, "0x1212100000000000000000000000000000000001": { "balance": "0", - "code": "0x6080604052600436106101b2575f3560e01c806389dc5c84116100e75780639f9d7f8111610087578063b88a802f11610062578063b88a802f1461070c578063d8ce95ab14610720578063da0b33171461074b578063db069ba514610776575f80fd5b80639f9d7f81146106d0578063a6580de8146106e4578063a681dfec146106f8575f80fd5b8063902bdc26116100c2578063902bdc261461064c5780639690293b1461067757806398ca58df1461068b5780639e40cdac146106b6575f80fd5b806389dc5c84146105f15780638e1900a81461060c5780638f1b321914610637575f80fd5b80634d21e42611610152578063683dd1911161012d578063683dd191146105595780636db504e7146105745780636dd7d8ea146105a8578063786255f1146105bb575f80fd5b80634d21e426146105055780634ff0876a146105305780636119053314610545575f80fd5b80630ea6a0411161018d5780630ea6a0411461047a5780631f26f256146104b157806343c14b22146104c65780634c569c25146104da575f80fd5b806303f187ea1461041e57806306a49fce146104465780630b2a85ea14610467575f80fd5b3661041a5733600361090960911b011461020b5760405162461bcd60e51b81526020600482015260156024820152741cda59194818d85b1b081b9bdd08185b1b1bddd959605a1b60448201526064015b60405180910390fd5b5f600d80548060200260200160405190810160405280929190818152602001828054801561026057602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610242575b505083519394505f925050505b818110156104185760095f84838151811061028a5761028a6119b1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20546103e85f54670de0b6b3a764000060065f8887815181106102d5576102d56119b1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20543461030891906119d9565b61031291906119d9565b61031c9190611a04565b6103269190611a04565b6103309190611a04565b600e5f858481518110610345576103456119b1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f205f82825461037a9190611a17565b92505081905550610410838281518110610396576103966119b1565b60200260200101516103e85f5460065f8887815181106103b8576103b86119b1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20546103e86103ed9190611a2a565b6103f790346119d9565b6104019190611a04565b61040b9190611a04565b6107a1565b60010161026d565b005b5f80fd5b348015610429575f80fd5b5061043360025481565b6040519081526020015b60405180910390f35b348015610451575f80fd5b5061045a61086b565b60405161043d9190611a3d565b610418610475366004611a89565b61087c565b348015610485575f80fd5b50610499610494366004611a89565b6109fd565b6040516001600160a01b03909116815260200161043d565b3480156104bc575f80fd5b50610433600c5481565b3480156104d1575f80fd5b50610418610a25565b3480156104e5575f80fd5b506104336104f4366004611abb565b600e6020525f908152604090205481565b348015610510575f80fd5b5061043361051f366004611abb565b60086020525f908152604090205481565b34801561053b575f80fd5b5061043360035481565b348015610550575f80fd5b50610418610b64565b348015610564575f80fd5b50610433670de0b6b3a764000081565b34801561057f575f80fd5b5061049961058e366004611abb565b600a6020525f90815260409020546001600160a01b031681565b6104186105b6366004611abb565b610c56565b3480156105c6575f80fd5b506104336105d5366004611ad4565b601160209081525f928352604080842090915290825290205481565b3480156105fc575f80fd5b50610499600361090960911b0181565b348015610617575f80fd5b50610433610626366004611abb565b600f6020525f908152604090205481565b348015610642575f80fd5b5061043360015481565b348015610657575f80fd5b50610433610666366004611abb565b60066020525f908152604090205481565b348015610682575f80fd5b50610418610e82565b348015610696575f80fd5b506104336106a5366004611abb565b60106020525f908152604090205481565b3480156106c1575f80fd5b506104996002600160a01b0381565b3480156106db575f80fd5b5061045a610f23565b3480156106ef575f80fd5b506104335f5481565b348015610703575f80fd5b50610418610f83565b348015610717575f80fd5b5061041861114e565b34801561072b575f80fd5b5061043361073a366004611abb565b60096020525f908152604090205481565b348015610756575f80fd5b50610433610765366004611abb565b60076020525f908152604090205481565b348015610781575f80fd5b50610433610790366004611abb565b600b6020525f908152604090205481565b604080515f808252602082019092526001600160a01b0384169083906040516107ca9190611b10565b5f6040518083038185875af1925050503d805f8114610804576040519150601f19603f3d011682016040523d82523d5f602084013e610809565b606091505b50509050806108665760405162461bcd60e51b8152602060048201526024808201527f736166655472616e736665724554483a20455448207472616e736665722066616044820152631a5b195960e21b6064820152608401610202565b505050565b606061087760046111b4565b905090565b6002543410156108c45760405162461bcd60e51b81526020600482015260136024820152721a5b9cdd59999a58da595b9d08185b5bdd5b9d606a1b6044820152606401610202565b6103e881106109045760405162461bcd60e51b815260206004820152600c60248201526b696e76616c6964207261746560a01b6044820152606401610202565b61090f6004336111c7565b1561094f5760405162461bcd60e51b815260206004820152601060248201526f63616e6469646174652065786973747360801b6044820152606401610202565b335f908152600760205260409020541561099e5760405162461bcd60e51b815260206004820152601060248201526f1b19599d081b9bdd0818db185a5b595960821b6044820152606401610202565b6109a96004336111ed565b50335f818152600660209081526040808320859055600882529182902034905590519182527feeda149c76076b34d4b9d8896c2f7efc0d33d1c7b53ea3c5db490d64613f603a91015b60405180910390a150565b600d8181548110610a0c575f80fd5b5f918252602090912001546001600160a01b0316905081565b335f908152600a6020908152604080832054600b909252909120546001600160a01b03909116908115801590610a5a57505f81115b610a9b5760405162461bcd60e51b81526020600482015260126024820152711c995d9bdad9481b9bdd08185b1b1bddd95960721b6044820152606401610202565b610aa53383611201565b6001600160a01b0382165f9081526009602052604081208054839290610acc908490611a2a565b9091555050335f818152600a6020908152604080832080546001600160a01b0319169055600b8252808320839055600f82528083208390556010909152812055610b1690826107a1565b604080513381526001600160a01b03841660208201529081018290527fb698e31a2abee5824d0d7bcfd2339aead7f9e9ae413fba50bf554ff3fa470b7b906060015b60405180910390a15050565b335f9081526007602052604090205415801590610ba65750600354610b8a9060026119d9565b335f90815260076020526040902054610ba39190611a17565b43115b610be95760405162461bcd60e51b81526020600482015260146024820152731dda5d1a191c985dc81b9bdd08185b1b1bddd95960621b6044820152606401610202565b335f81815260086020908152604080832080549084905560078352818420849055600690925282209190915590610c2090826107a1565b60408051338152602081018390527f142e26dcca50281d2c46d90446bfc1c9bc260cef355ce917a52f1fec7c54b5bf91016109f2565b600154341015610c9e5760405162461bcd60e51b81526020600482015260136024820152721a5b9cdd59999a58da595b9d08185b5bdd5b9d606a1b6044820152606401610202565b610ca96004826111c7565b610ced5760405162461bcd60e51b815260206004820152601560248201527418d85b991a59185d19481b9bdd08185b1b1bddd959605a1b6044820152606401610202565b335f908152600a60205260409020546001600160a01b03908116908216811480610d1e57506001600160a01b038116155b610d6a5760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c79206f6e652063686f69636520697320616c6c6f7765640000000000006044820152606401610202565b6001600160a01b03811615610d8857610d833382611201565b610dcb565b335f818152600a6020908152604080832080546001600160a01b0319166001600160a01b0388169081179091558352600e825280832054938352600f9091529020555b335f908152600b602052604081208054349290610de9908490611a17565b90915550506001600160a01b0382165f9081526009602052604081208054349290610e15908490611a17565b90915550506001600160a01b038116610e3a57335f9081526010602052604090204390555b604080513381526001600160a01b038416602082015234918101919091527f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc90606001610b58565b610e8d6004336111c7565b610ed05760405162461bcd60e51b815260206004820152601460248201527363616e646964617465206e6f742065786973747360601b6044820152606401610202565b610edb600433611330565b50335f8181526007602090815260409182902043905590519182527f7c79e6e24ed041d1072d54523b53956f01b91b835f0490856370594d9d14470e910160405180910390a1565b6060600d805480602002602001604051908101604052809291908181526020018280548015610f7957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610f5b575b5050505050905090565b336002600160a01b0314610fd15760405162461bcd60e51b81526020600482015260156024820152741cda59194818d85b1b081b9bdd08185b1b1bddd959605a1b6044820152606401610202565b600361090960911b016001600160a01b0316633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611011575f80fd5b505af1158015611023573d5f803e3d5ffd5b50505050600354600c546110379190611a17565b43101561104057565b5f61104b60046111b4565b80519091505f5b818110156110fc57600e5f84838151811061106f5761106f6119b1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f205460115f8584815181106110ac576110ac6119b1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f205f600354600c546110e49190611a04565b815260208101919091526040015f2055600101611052565b5043600c55611109611344565b805161111d91600d9160209091019061193a565b507fe59e3b36b5c97b419925b60c92f5a4324c993934eb9cfe5232def67c1739337c600d604051610b589190611b3c565b335f908152600a60205260409020546001600160a01b0316806111a75760405162461bcd60e51b815260206004820152601160248201527018db185a5b481b9bdd08185b1b1bddd959607a1b6044820152606401610202565b6111b13382611201565b50565b60605f6111c0836114ba565b9392505050565b6001600160a01b0381165f90815260018301602052604081205415155b90505b92915050565b5f6111e4836001600160a01b038416611513565b6001600160a01b038083165f90815260106020908152604080832054600f8352818420549486168452600e835281842054601190935290832060035491949391829061124e600188611a2a565b6112589190611a04565b611263906001611a17565b81526020019081526020015f205490508281111561127f578092505b5f670de0b6b3a76400006112938585611a2a565b6001600160a01b0389165f908152600b60205260409020546112b591906119d9565b6112bf9190611a04565b6001600160a01b0388165f908152600f6020526040902084905590506112e587826107a1565b604080516001600160a01b0389168152602081018390527fbeceb521ccd2816457290c3d1cb70cc1537f14307f2d9ac26a5093a38ea40948910160405180910390a150505050505050565b5f6111e4836001600160a01b03841661155f565b60605f61134f61086b565b80519091505f8167ffffffffffffffff81111561136e5761136e611afc565b604051908082528060200260200182016040528015611397578160200160208202803683370190505b5090505f5b828110156114065760095f8583815181106113b9576113b96119b1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20548282815181106113f3576113f36119b1565b602090810291909101015260010161139c565b5061141383825f54611649565b5f805467ffffffffffffffff81111561142e5761142e611afc565b604051908082528060200260200182016040528015611457578160200160208202803683370190505b5090505f5b5f548110156114b157848181518110611477576114776119b1565b6020026020010151828281518110611491576114916119b1565b6001600160a01b039092166020928302919091019091015260010161145c565b50949350505050565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561150757602002820191905f5260205f20905b8154815260200190600101908083116114f3575b50505050509050919050565b5f81815260018301602052604081205461155857508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556111e7565b505f6111e7565b5f8181526001830160205260408120548015611639575f611581600183611a2a565b85549091505f9061159490600190611a2a565b90508082146115f3575f865f0182815481106115b2576115b26119b1565b905f5260205f200154905080875f0184815481106115d2576115d26119b1565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061160457611604611b7f565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506111e7565b5f9150506111e7565b5092915050565b82515f6001611659600285611b93565b6116639190611bbf565b90505b5f811261168b576116798585838661176f565b8061168381611bde565b915050611666565b50815b8181101561176857835f815181106116a8576116a86119b1565b60200260200101518482815181106116c2576116c26119b1565b60200260200101511115611760578381815181106116e2576116e26119b1565b6020026020010151845f815181106116fc576116fc6119b1565b60200260200101818152505084818151811061171a5761171a6119b1565b6020026020010151855f81518110611734576117346119b1565b60200260200101906001600160a01b031690816001600160a01b03168152505061176085855f8661176f565b60010161168e565b5050505050565b5f61177b8360026119d9565b611786906001611a17565b90505b81811015611768578161179d826001611a17565b1080156117e55750836117b1826001611a17565b815181106117c1576117c16119b1565b60200260200101518482815181106117db576117db6119b1565b6020026020010151115b156117f8576117f5600182611a17565b90505b83838151811061180a5761180a6119b1565b6020026020010151848281518110611824576118246119b1565b60200260200101511161176857838381518110611843576118436119b1565b602002602001015184828151811061185d5761185d6119b1565b6020026020010151858381518110611877576118776119b1565b60200260200101868681518110611890576118906119b1565b60200260200101828152508281525050508483815181106118b3576118b36119b1565b60200260200101518582815181106118cd576118cd6119b1565b60200260200101518683815181106118e7576118e76119b1565b60200260200101878681518110611900576119006119b1565b6001600160a01b039384166020918202929092010152911690529150816119288160026119d9565b611933906001611a17565b9050611789565b828054828255905f5260205f2090810192821561198d579160200282015b8281111561198d57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190611958565b5061199992915061199d565b5090565b5b80821115611999575f815560010161199e565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176111e7576111e76119c5565b634e487b7160e01b5f52601260045260245ffd5b5f82611a1257611a126119f0565b500490565b808201808211156111e7576111e76119c5565b818103818111156111e7576111e76119c5565b602080825282518282018190525f9190848201906040850190845b81811015611a7d5783516001600160a01b031683529284019291840191600101611a58565b50909695505050505050565b5f60208284031215611a99575f80fd5b5035919050565b80356001600160a01b0381168114611ab6575f80fd5b919050565b5f60208284031215611acb575f80fd5b6111e482611aa0565b5f8060408385031215611ae5575f80fd5b611aee83611aa0565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b5f82515f5b81811015611b2f5760208186018101518583015201611b15565b505f920191825250919050565b602080825282548282018190525f8481528281209092916040850190845b81811015611a7d5783546001600160a01b031683526001938401939285019201611b5a565b634e487b7160e01b5f52603160045260245ffd5b5f82611ba157611ba16119f0565b600160ff1b82145f1984141615611bba57611bba6119c5565b500590565b8181035f831280158383131683831282161715611642576116426119c5565b5f600160ff1b8201611bf257611bf26119c5565b505f19019056fea26469706673582212202abe25305608726694348364ab10e4772662e4e71c0dff136f5af913f9daf21564736f6c63430008180033" + "code": "0x6080604052600436106101b2575f3560e01c806389dc5c84116100e75780639f9d7f8111610087578063b88a802f11610062578063b88a802f146107e2578063d8ce95ab146107f6578063da0b331714610821578063db069ba51461084c575f80fd5b80639f9d7f81146107a6578063a6580de8146107ba578063a681dfec146107ce575f80fd5b8063902bdc26116100c2578063902bdc26146107155780639690293b1461074057806398ca58df146107545780639e40cdac1461077f575f80fd5b806389dc5c84146106ae5780638e1900a8146106d55780638f1b321914610700575f80fd5b80634d21e42611610152578063683dd1911161012d578063683dd191146106095780636db504e7146106245780636dd7d8ea14610665578063786255f114610678575f80fd5b80634d21e426146105b55780634ff0876a146105e057806361190533146105f5575f80fd5b80630ea6a0411161018d5780630ea6a0411461051d5780631f26f2561461056157806343c14b22146105765780634c569c251461058a575f80fd5b806303f187ea146104c157806306a49fce146104e95780630b2a85ea1461050a575f80fd5b366104bd573373121200000000000000000000000000000000000314610239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f736964652063616c6c206e6f7420616c6c6f776564000000000000000000000060448201526064015b60405180910390fd5b5f600d80548060200260200160405190810160405280929190818152602001828054801561029b57602002820191905f5260205f20905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610270575b505083519394505f925050505b818110156104bb5760095f8483815181106102c5576102c5611e78565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e85f54670de0b6b3a764000060065f88878151811061032a5761032a611e78565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054346103779190611ed2565b6103819190611ed2565b61038b9190611f16565b6103959190611f16565b61039f9190611f16565b600e5f8584815181106103b4576103b4611e78565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546104039190611f29565b925050819055506104b383828151811061041f5761041f611e78565b60200260200101516103e85f5460065f88878151811061044157610441611e78565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e86104909190611f3c565b61049a9034611ed2565b6104a49190611f16565b6104ae9190611f16565b610877565b6001016102a8565b005b5f80fd5b3480156104cc575f80fd5b506104d660025481565b6040519081526020015b60405180910390f35b3480156104f4575f80fd5b506104fd610981565b6040516104e09190611f4f565b6104bb610518366004611fa8565b610992565b348015610528575f80fd5b5061053c610537366004611fa8565b610bb0565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016104e0565b34801561056c575f80fd5b506104d6600c5481565b348015610581575f80fd5b506104bb610be5565b348015610595575f80fd5b506104d66105a4366004611fe7565b600e6020525f908152604090205481565b3480156105c0575f80fd5b506104d66105cf366004611fe7565b60086020525f908152604090205481565b3480156105eb575f80fd5b506104d660035481565b348015610600575f80fd5b506104bb610d88565b348015610614575f80fd5b506104d6670de0b6b3a764000081565b34801561062f575f80fd5b5061053c61063e366004611fe7565b600a6020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6104bb610673366004611fe7565b610e9d565b348015610683575f80fd5b506104d6610692366004612000565b601160209081525f928352604080842090915290825290205481565b3480156106b9575f80fd5b5061053c73121200000000000000000000000000000000000381565b3480156106e0575f80fd5b506104d66106ef366004611fe7565b600f6020525f908152604090205481565b34801561070b575f80fd5b506104d660015481565b348015610720575f80fd5b506104d661072f366004611fe7565b60066020525f908152604090205481565b34801561074b575f80fd5b506104bb61119c565b34801561075f575f80fd5b506104d661076e366004611fe7565b60106020525f908152604090205481565b34801561078a575f80fd5b5061053c73fffffffffffffffffffffffffffffffffffffffe81565b3480156107b1575f80fd5b506104fd611260565b3480156107c5575f80fd5b506104d65f5481565b3480156107d9575f80fd5b506104bb6112cd565b3480156107ed575f80fd5b506104bb611514565b348015610801575f80fd5b506104d6610810366004611fe7565b60096020525f908152604090205481565b34801561082c575f80fd5b506104d661083b366004611fe7565b60076020525f908152604090205481565b348015610857575f80fd5b506104d6610866366004611fe7565b600b6020525f908152604090205481565b604080515f8082526020820190925273ffffffffffffffffffffffffffffffffffffffff84169083906040516108ad9190612055565b5f6040518083038185875af1925050503d805f81146108e7576040519150601f19603f3d011682016040523d82523d5f602084013e6108ec565b606091505b505090508061097c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f736166655472616e736665724554483a20455448207472616e7366657220666160448201527f696c6564000000000000000000000000000000000000000000000000000000006064820152608401610230565b505050565b606061098d60046115ad565b905090565b6002543410156109fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e73756666696369656e7420616d6f756e74000000000000000000000000006044820152606401610230565b6103e88110610a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f696e76616c6964207261746500000000000000000000000000000000000000006044820152606401610230565b610a746004336115c0565b15610adb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f63616e64696461746520657869737473000000000000000000000000000000006044820152606401610230565b335f9081526007602052604090205415610b51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6c656674206e6f7420636c61696d6564000000000000000000000000000000006044820152606401610230565b610b5c6004336115f3565b50335f818152600660209081526040808320859055600882529182902034905590519182527feeda149c76076b34d4b9d8896c2f7efc0d33d1c7b53ea3c5db490d64613f603a91015b60405180910390a150565b600d8181548110610bbf575f80fd5b5f9182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b335f908152600a6020908152604080832054600b9092529091205473ffffffffffffffffffffffffffffffffffffffff909116908115801590610c2757505f81115b610c8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f7265766f6b65206e6f7420616c6c6f77656400000000000000000000000000006044820152606401610230565b610c973383611614565b73ffffffffffffffffffffffffffffffffffffffff82165f9081526009602052604081208054839290610ccb908490611f3c565b9091555050335f818152600a6020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055600b8252808320839055600f82528083208390556010909152812055610d2d9082610877565b6040805133815273ffffffffffffffffffffffffffffffffffffffff841660208201529081018290527fb698e31a2abee5824d0d7bcfd2339aead7f9e9ae413fba50bf554ff3fa470b7b906060015b60405180910390a15050565b335f9081526007602052604090205415801590610dca5750600354610dae906002611ed2565b335f90815260076020526040902054610dc79190611f29565b43115b610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7769746864726177206e6f7420616c6c6f7765640000000000000000000000006044820152606401610230565b335f81815260086020908152604080832080549084905560078352818420849055600690925282209190915590610e679082610877565b60408051338152602081018390527f142e26dcca50281d2c46d90446bfc1c9bc260cef355ce917a52f1fec7c54b5bf9101610ba5565b600154341015610f09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e73756666696369656e7420616d6f756e74000000000000000000000000006044820152606401610230565b610f146004826115c0565b610f7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f63616e646964617465206e6f7420616c6c6f77656400000000000000000000006044820152606401610230565b335f908152600a602052604090205473ffffffffffffffffffffffffffffffffffffffff908116908216811480610fc5575073ffffffffffffffffffffffffffffffffffffffff8116155b61102b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6f6e6c79206f6e652063686f69636520697320616c6c6f7765640000000000006044820152606401610230565b73ffffffffffffffffffffffffffffffffffffffff811615611056576110513382611614565b6110be565b335f818152600a6020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff88169081179091558352600e825280832054938352600f9091529020555b335f908152600b6020526040812080543492906110dc908490611f29565b909155505073ffffffffffffffffffffffffffffffffffffffff82165f9081526009602052604081208054349290611115908490611f29565b909155505073ffffffffffffffffffffffffffffffffffffffff811661114757335f9081526010602052604090204390555b6040805133815273ffffffffffffffffffffffffffffffffffffffff8416602082015234918101919091527f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc90606001610d7c565b6111a76004336115c0565b61120d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f63616e646964617465206e6f74206578697374730000000000000000000000006044820152606401610230565b611218600433611777565b50335f8181526007602090815260409182902043905590519182527f7c79e6e24ed041d1072d54523b53956f01b91b835f0490856370594d9d14470e910160405180910390a1565b6060600d8054806020026020016040519081016040528092919081815260200182805480156112c357602002820191905f5260205f20905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611298575b5050505050905090565b3373fffffffffffffffffffffffffffffffffffffffe1461134a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f736964652063616c6c206e6f7420616c6c6f77656400000000000000000000006044820152606401610230565b73121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156113a3575f80fd5b505af11580156113b5573d5f803e3d5ffd5b50505050600354600c546113c99190611f29565b4310156113d257565b5f6113dd60046115ad565b80519091505f5b818110156114c257600e5f84838151811061140157611401611e78565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205460115f85848151811061145857611458611e78565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f600354600c546114aa9190611f16565b815260208101919091526040015f20556001016113e4565b5043600c556114cf611798565b80516114e391600d91602090910190611ddc565b507fe59e3b36b5c97b419925b60c92f5a4324c993934eb9cfe5232def67c1739337c600d604051610d7c9190612081565b335f908152600a602052604090205473ffffffffffffffffffffffffffffffffffffffff16806115a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f636c61696d206e6f7420616c6c6f7765640000000000000000000000000000006044820152606401610230565b6115aa3382611614565b50565b60605f6115b983611935565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260018301602052604081205415155b90505b92915050565b5f6115ea8373ffffffffffffffffffffffffffffffffffffffff841661198e565b73ffffffffffffffffffffffffffffffffffffffff8083165f90815260106020908152604080832054600f8352818420549486168452600e835281842054601190935290832060035491949391829061166e600188611f3c565b6116789190611f16565b611683906001611f29565b81526020019081526020015f205490508281111561169f578092505b5f670de0b6b3a76400006116b38585611f3c565b73ffffffffffffffffffffffffffffffffffffffff89165f908152600b60205260409020546116e29190611ed2565b6116ec9190611f16565b73ffffffffffffffffffffffffffffffffffffffff88165f908152600f60205260409020849055905061171f8782610877565b6040805173ffffffffffffffffffffffffffffffffffffffff89168152602081018390527fbeceb521ccd2816457290c3d1cb70cc1537f14307f2d9ac26a5093a38ea40948910160405180910390a150505050505050565b5f6115ea8373ffffffffffffffffffffffffffffffffffffffff84166119da565b60605f6117a3610981565b80519091505f8167ffffffffffffffff8111156117c2576117c2612028565b6040519080825280602002602001820160405280156117eb578160200160208202803683370190505b5090505f5b828110156118745760095f85838151811061180d5761180d611e78565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205482828151811061186157611861611e78565b60209081029190910101526001016117f0565b5061188183825f54611ac4565b5f805467ffffffffffffffff81111561189c5761189c612028565b6040519080825280602002602001820160405280156118c5578160200160208202803683370190505b5090505f5b5f5481101561192c578481815181106118e5576118e5611e78565b60200260200101518282815181106118ff576118ff611e78565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526001016118ca565b50949350505050565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561198257602002820191905f5260205f20905b81548152602001906001019080831161196e575b50505050509050919050565b5f8181526001830160205260408120546119d357508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556115ed565b505f6115ed565b5f8181526001830160205260408120548015611ab4575f6119fc600183611f3c565b85549091505f90611a0f90600190611f3c565b9050808214611a6e575f865f018281548110611a2d57611a2d611e78565b905f5260205f200154905080875f018481548110611a4d57611a4d611e78565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080611a7f57611a7f6120d1565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506115ed565b5f9150506115ed565b5092915050565b82515f6001611ad46002856120fe565b611ade9190612165565b90505b5f8112611b0657611af485858386611c04565b80611afe81612184565b915050611ae1565b50815b81811015611bfd57835f81518110611b2357611b23611e78565b6020026020010151848281518110611b3d57611b3d611e78565b60200260200101511115611bf557838181518110611b5d57611b5d611e78565b6020026020010151845f81518110611b7757611b77611e78565b602002602001018181525050848181518110611b9557611b95611e78565b6020026020010151855f81518110611baf57611baf611e78565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611bf585855f86611c04565b600101611b09565b5050505050565b5f611c10836002611ed2565b611c1b906001611f29565b90505b81811015611bfd5781611c32826001611f29565b108015611c7a575083611c46826001611f29565b81518110611c5657611c56611e78565b6020026020010151848281518110611c7057611c70611e78565b6020026020010151115b15611c8d57611c8a600182611f29565b90505b838381518110611c9f57611c9f611e78565b6020026020010151848281518110611cb957611cb9611e78565b602002602001015111611bfd57838381518110611cd857611cd8611e78565b6020026020010151848281518110611cf257611cf2611e78565b6020026020010151858381518110611d0c57611d0c611e78565b60200260200101868681518110611d2557611d25611e78565b6020026020010182815250828152505050848381518110611d4857611d48611e78565b6020026020010151858281518110611d6257611d62611e78565b6020026020010151868381518110611d7c57611d7c611e78565b60200260200101878681518110611d9557611d95611e78565b73ffffffffffffffffffffffffffffffffffffffff938416602091820292909201015291169052915081611dca816002611ed2565b611dd5906001611f29565b9050611c1e565b828054828255905f5260205f20908101928215611e54579160200282015b82811115611e5457825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190611dfa565b50611e60929150611e64565b5090565b5b80821115611e60575f8155600101611e65565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820281158282048414176115ed576115ed611ea5565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f82611f2457611f24611ee9565b500490565b808201808211156115ed576115ed611ea5565b818103818111156115ed576115ed611ea5565b602080825282518282018190525f9190848201906040850190845b81811015611f9c57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611f6a565b50909695505050505050565b5f60208284031215611fb8575f80fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611fe2575f80fd5b919050565b5f60208284031215611ff7575f80fd5b6115ea82611fbf565b5f8060408385031215612011575f80fd5b61201a83611fbf565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82515f5b81811015612074576020818601810151858301520161205a565b505f920191825250919050565b602080825282548282018190525f8481528281209092916040850190845b81811015611f9c57835473ffffffffffffffffffffffffffffffffffffffff168352600193840193928501920161209f565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f8261210c5761210c611ee9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561216057612160611ea5565b500590565b8181035f831280158383131683831282161715611abd57611abd611ea5565b5f7f800000000000000000000000000000000000000000000000000000000000000082036121b4576121b4611ea5565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220fcba8ea1ad4d6b5fb44979e3302ef4c7131c8c260becbb90d014372afd04805364736f6c63430008180033" }, "0x1212100000000000000000000000000000000002": { "balance": "0", From c81008bdd06e9d6e83996828acec6f70cb1fa55d Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Sat, 23 Mar 2024 22:44:27 +0800 Subject: [PATCH 63/66] update govreward genesis with new configuration --- genesis.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/genesis.json b/genesis.json index 2641b44e62..eb01531b6f 100644 --- a/genesis.json +++ b/genesis.json @@ -67,7 +67,7 @@ }, "0x1212000000000000000000000000000000000003": { "balance": "0", - "code": "0x608060405260043610610037575f3560e01c80631633da6e146100425780633ccfd60b1461006c5780635aa6e675146100825761003e565b3661003e57005b5f80fd5b34801561004d575f80fd5b506100566100ac565b60405161006391906103d3565b60405180910390f35b348015610077575f80fd5b50610080610137565b005b34801561008d575f80fd5b506100966101d9565b6040516100a39190610402565b60405180910390f35b606073121200000000000000000000000000000000000173ffffffffffffffffffffffffffffffffffffffff16639f9d7f816040518163ffffffff1660e01b81526004015f60405180830381865afa15801561010a573d5f803e3d5ffd5b505050506040513d5f823e3d601f19601f8201168201806040525081019061013291906105a6565b905090565b73121200000000000000000000000000000000000173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101b090610647565b60405180910390fd5b6101d7731212000000000000000000000000000000000001476101f1565b565b73121200000000000000000000000000000000000181565b5f8273ffffffffffffffffffffffffffffffffffffffff16825f67ffffffffffffffff81111561022457610223610440565b5b6040519080825280601f01601f1916602001820160405280156102565781602001600182028036833780820191505090505b5060405161026491906106d1565b5f6040518083038185875af1925050503d805f811461029e576040519150601f19603f3d011682016040523d82523d5f602084013e6102a3565b606091505b50509050806102e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102de90610757565b60405180910390fd5b505050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61033e82610315565b9050919050565b61034e81610334565b82525050565b5f61035f8383610345565b60208301905092915050565b5f602082019050919050565b5f610381826102ec565b61038b81856102f6565b935061039683610306565b805f5b838110156103c65781516103ad8882610354565b97506103b88361036b565b925050600181019050610399565b5085935050505092915050565b5f6020820190508181035f8301526103eb8184610377565b905092915050565b6103fc81610334565b82525050565b5f6020820190506104155f8301846103f3565b92915050565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61047682610430565b810181811067ffffffffffffffff8211171561049557610494610440565b5b80604052505050565b5f6104a761041b565b90506104b3828261046d565b919050565b5f67ffffffffffffffff8211156104d2576104d1610440565b5b602082029050602081019050919050565b5f80fd5b6104f081610334565b81146104fa575f80fd5b50565b5f8151905061050b816104e7565b92915050565b5f61052361051e846104b8565b61049e565b90508083825260208201905060208402830185811115610546576105456104e3565b5b835b8181101561056f578061055b88826104fd565b845260208401935050602081019050610548565b5050509392505050565b5f82601f83011261058d5761058c61042c565b5b815161059d848260208601610511565b91505092915050565b5f602082840312156105bb576105ba610424565b5b5f82015167ffffffffffffffff8111156105d8576105d7610428565b5b6105e484828501610579565b91505092915050565b5f82825260208201905092915050565b7f4e6f7420676f7665726e616e63650000000000000000000000000000000000005f82015250565b5f610631600e836105ed565b915061063c826105fd565b602082019050919050565b5f6020820190508181035f83015261065e81610625565b9050919050565b5f81519050919050565b5f81905092915050565b5f5b8381101561069657808201518184015260208101905061067b565b5f8484015250505050565b5f6106ab82610665565b6106b5818561066f565b93506106c5818560208601610679565b80840191505092915050565b5f6106dc82846106a1565b915081905092915050565b7f736166655472616e736665724554483a20455448207472616e736665722066615f8201527f696c656400000000000000000000000000000000000000000000000000000000602082015250565b5f6107416024836105ed565b915061074c826106e7565b604082019050919050565b5f6020820190508181035f83015261076e81610735565b905091905056fea2646970667358221220a68c92822c68b5b448bc853ee8426363344cf81c780422ede6e9786d4500aec564736f6c63430008180033" + "code": "0x608060405260043610610036575f3560e01c80631633da6e146100415780633ccfd60b1461006b5780635aa6e67514610081575f80fd5b3661003d57005b5f80fd5b34801561004c575f80fd5b506100556100cd565b6040516100629190610327565b60405180910390f35b348015610076575f80fd5b5061007f610175565b005b34801561008c575f80fd5b506100a873121200000000000000000000000000000000000181565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610062565b606073121200000000000000000000000000000000000173ffffffffffffffffffffffffffffffffffffffff16639f9d7f816040518163ffffffff1660e01b81526004015f60405180830381865afa15801561012b573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261017091908101906103d5565b905090565b33731212000000000000000000000000000000000001146101f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e6f7420676f7665726e616e636500000000000000000000000000000000000060448201526064015b60405180910390fd5b471561021b5761021b7312120000000000000000000000000000000000014761021d565b565b604080515f8082526020820190925273ffffffffffffffffffffffffffffffffffffffff841690839060405161025391906104b3565b5f6040518083038185875af1925050503d805f811461028d576040519150601f19603f3d011682016040523d82523d5f602084013e610292565b606091505b5050905080610322576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f736166655472616e736665724554483a20455448207472616e7366657220666160448201527f696c65640000000000000000000000000000000000000000000000000000000060648201526084016101ee565b505050565b602080825282518282018190525f9190848201906040850190845b8181101561037457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610342565b50909695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b805173ffffffffffffffffffffffffffffffffffffffff811681146103d0575f80fd5b919050565b5f60208083850312156103e6575f80fd5b825167ffffffffffffffff808211156103fd575f80fd5b818501915085601f830112610410575f80fd5b81518181111561042257610422610380565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561046557610465610380565b604052918252848201925083810185019188831115610482575f80fd5b938501935b828510156104a757610498856103ad565b84529385019392850192610487565b98975050505050505050565b5f82515f5b818110156104d257602081860181015185830152016104b8565b505f92019182525091905056fea2646970667358221220bf0616af90ea4545d17e405fa3ba4df3062321a9a535fe45876c3962cc8f2f8c64736f6c63430008180033" }, "0x1212100000000000000000000000000000000001": { "balance": "0", From 6f8beddbf3ae8480d32d1ae95eea67fc1eb1c9f6 Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Sat, 23 Mar 2024 23:04:05 +0800 Subject: [PATCH 64/66] format --- contracts/solidity/GovernanceV2.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index ba5c66003b..27df439df9 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -172,9 +172,9 @@ contract GovernanceV2 is IGovernanceV2 { // update votes votedAmount[msg.sender] += msg.value; receivedVotes[candidateTo] += msg.value; - // NOTE: the left reward in the epoch of first vote will be unclaimable. + // NOTE: the left reward in the first epoch of first vote will be unclaimable. if (votedCandidate == address(0)) { - voteHeight[msg.sender] = block.number; + voteHeight[msg.sender] = block.number; } emit Vote(msg.sender, candidateTo, msg.value); From d5992c25c209f4d9ea50710f2e119c21084dddbd Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Sat, 23 Mar 2024 23:42:31 +0800 Subject: [PATCH 65/66] fix settle reward --- contracts/solidity/GovernanceV2.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/contracts/solidity/GovernanceV2.sol b/contracts/solidity/GovernanceV2.sol index 27df439df9..6c02a8c945 100644 --- a/contracts/solidity/GovernanceV2.sol +++ b/contracts/solidity/GovernanceV2.sol @@ -215,9 +215,7 @@ contract GovernanceV2 is IGovernanceV2 { require(msg.sender == sysCall, "side call not allowed"); // only settle validator reward if there is no epoch change IGovReward(govReward).withdraw(); - if (block.number < currentEpochStartHeight + epochDuration) { - return; - } + if (block.number < currentEpochStartHeight + epochDuration) return; // update tag values address[] memory candidates = candidateList.values(); @@ -243,6 +241,7 @@ contract GovernanceV2 is IGovernanceV2 { uint height = voteHeight[voter]; uint lastGasPerVote = voterGasPerVote[voter]; uint latestGasPerVote = candidateGasPerVote[candidate]; + if (currentEpochStartHeight <= height) return; // NOTE: suppose epoch change always happens at the beginning of a block, then vote in that block should wait another epoch to farm reward uint voteEpochEndGasPerVote = epochStartGasPerVote[candidate][ From 8e804969f78d7f5c1b0ad91d7abfab091016709e Mon Sep 17 00:00:00 2001 From: txhsl <799498265@qq.com> Date: Sun, 24 Mar 2024 00:26:08 +0800 Subject: [PATCH 66/66] update genesis file --- genesis.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/genesis.json b/genesis.json index eb01531b6f..646f38f812 100644 --- a/genesis.json +++ b/genesis.json @@ -71,7 +71,7 @@ }, "0x1212100000000000000000000000000000000001": { "balance": "0", - "code": "0x6080604052600436106101b2575f3560e01c806389dc5c84116100e75780639f9d7f8111610087578063b88a802f11610062578063b88a802f146107e2578063d8ce95ab146107f6578063da0b331714610821578063db069ba51461084c575f80fd5b80639f9d7f81146107a6578063a6580de8146107ba578063a681dfec146107ce575f80fd5b8063902bdc26116100c2578063902bdc26146107155780639690293b1461074057806398ca58df146107545780639e40cdac1461077f575f80fd5b806389dc5c84146106ae5780638e1900a8146106d55780638f1b321914610700575f80fd5b80634d21e42611610152578063683dd1911161012d578063683dd191146106095780636db504e7146106245780636dd7d8ea14610665578063786255f114610678575f80fd5b80634d21e426146105b55780634ff0876a146105e057806361190533146105f5575f80fd5b80630ea6a0411161018d5780630ea6a0411461051d5780631f26f2561461056157806343c14b22146105765780634c569c251461058a575f80fd5b806303f187ea146104c157806306a49fce146104e95780630b2a85ea1461050a575f80fd5b366104bd573373121200000000000000000000000000000000000314610239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f736964652063616c6c206e6f7420616c6c6f776564000000000000000000000060448201526064015b60405180910390fd5b5f600d80548060200260200160405190810160405280929190818152602001828054801561029b57602002820191905f5260205f20905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610270575b505083519394505f925050505b818110156104bb5760095f8483815181106102c5576102c5611e78565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e85f54670de0b6b3a764000060065f88878151811061032a5761032a611e78565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054346103779190611ed2565b6103819190611ed2565b61038b9190611f16565b6103959190611f16565b61039f9190611f16565b600e5f8584815181106103b4576103b4611e78565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546104039190611f29565b925050819055506104b383828151811061041f5761041f611e78565b60200260200101516103e85f5460065f88878151811061044157610441611e78565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e86104909190611f3c565b61049a9034611ed2565b6104a49190611f16565b6104ae9190611f16565b610877565b6001016102a8565b005b5f80fd5b3480156104cc575f80fd5b506104d660025481565b6040519081526020015b60405180910390f35b3480156104f4575f80fd5b506104fd610981565b6040516104e09190611f4f565b6104bb610518366004611fa8565b610992565b348015610528575f80fd5b5061053c610537366004611fa8565b610bb0565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016104e0565b34801561056c575f80fd5b506104d6600c5481565b348015610581575f80fd5b506104bb610be5565b348015610595575f80fd5b506104d66105a4366004611fe7565b600e6020525f908152604090205481565b3480156105c0575f80fd5b506104d66105cf366004611fe7565b60086020525f908152604090205481565b3480156105eb575f80fd5b506104d660035481565b348015610600575f80fd5b506104bb610d88565b348015610614575f80fd5b506104d6670de0b6b3a764000081565b34801561062f575f80fd5b5061053c61063e366004611fe7565b600a6020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6104bb610673366004611fe7565b610e9d565b348015610683575f80fd5b506104d6610692366004612000565b601160209081525f928352604080842090915290825290205481565b3480156106b9575f80fd5b5061053c73121200000000000000000000000000000000000381565b3480156106e0575f80fd5b506104d66106ef366004611fe7565b600f6020525f908152604090205481565b34801561070b575f80fd5b506104d660015481565b348015610720575f80fd5b506104d661072f366004611fe7565b60066020525f908152604090205481565b34801561074b575f80fd5b506104bb61119c565b34801561075f575f80fd5b506104d661076e366004611fe7565b60106020525f908152604090205481565b34801561078a575f80fd5b5061053c73fffffffffffffffffffffffffffffffffffffffe81565b3480156107b1575f80fd5b506104fd611260565b3480156107c5575f80fd5b506104d65f5481565b3480156107d9575f80fd5b506104bb6112cd565b3480156107ed575f80fd5b506104bb611514565b348015610801575f80fd5b506104d6610810366004611fe7565b60096020525f908152604090205481565b34801561082c575f80fd5b506104d661083b366004611fe7565b60076020525f908152604090205481565b348015610857575f80fd5b506104d6610866366004611fe7565b600b6020525f908152604090205481565b604080515f8082526020820190925273ffffffffffffffffffffffffffffffffffffffff84169083906040516108ad9190612055565b5f6040518083038185875af1925050503d805f81146108e7576040519150601f19603f3d011682016040523d82523d5f602084013e6108ec565b606091505b505090508061097c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f736166655472616e736665724554483a20455448207472616e7366657220666160448201527f696c6564000000000000000000000000000000000000000000000000000000006064820152608401610230565b505050565b606061098d60046115ad565b905090565b6002543410156109fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e73756666696369656e7420616d6f756e74000000000000000000000000006044820152606401610230565b6103e88110610a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f696e76616c6964207261746500000000000000000000000000000000000000006044820152606401610230565b610a746004336115c0565b15610adb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f63616e64696461746520657869737473000000000000000000000000000000006044820152606401610230565b335f9081526007602052604090205415610b51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6c656674206e6f7420636c61696d6564000000000000000000000000000000006044820152606401610230565b610b5c6004336115f3565b50335f818152600660209081526040808320859055600882529182902034905590519182527feeda149c76076b34d4b9d8896c2f7efc0d33d1c7b53ea3c5db490d64613f603a91015b60405180910390a150565b600d8181548110610bbf575f80fd5b5f9182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b335f908152600a6020908152604080832054600b9092529091205473ffffffffffffffffffffffffffffffffffffffff909116908115801590610c2757505f81115b610c8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f7265766f6b65206e6f7420616c6c6f77656400000000000000000000000000006044820152606401610230565b610c973383611614565b73ffffffffffffffffffffffffffffffffffffffff82165f9081526009602052604081208054839290610ccb908490611f3c565b9091555050335f818152600a6020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055600b8252808320839055600f82528083208390556010909152812055610d2d9082610877565b6040805133815273ffffffffffffffffffffffffffffffffffffffff841660208201529081018290527fb698e31a2abee5824d0d7bcfd2339aead7f9e9ae413fba50bf554ff3fa470b7b906060015b60405180910390a15050565b335f9081526007602052604090205415801590610dca5750600354610dae906002611ed2565b335f90815260076020526040902054610dc79190611f29565b43115b610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7769746864726177206e6f7420616c6c6f7765640000000000000000000000006044820152606401610230565b335f81815260086020908152604080832080549084905560078352818420849055600690925282209190915590610e679082610877565b60408051338152602081018390527f142e26dcca50281d2c46d90446bfc1c9bc260cef355ce917a52f1fec7c54b5bf9101610ba5565b600154341015610f09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e73756666696369656e7420616d6f756e74000000000000000000000000006044820152606401610230565b610f146004826115c0565b610f7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f63616e646964617465206e6f7420616c6c6f77656400000000000000000000006044820152606401610230565b335f908152600a602052604090205473ffffffffffffffffffffffffffffffffffffffff908116908216811480610fc5575073ffffffffffffffffffffffffffffffffffffffff8116155b61102b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6f6e6c79206f6e652063686f69636520697320616c6c6f7765640000000000006044820152606401610230565b73ffffffffffffffffffffffffffffffffffffffff811615611056576110513382611614565b6110be565b335f818152600a6020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff88169081179091558352600e825280832054938352600f9091529020555b335f908152600b6020526040812080543492906110dc908490611f29565b909155505073ffffffffffffffffffffffffffffffffffffffff82165f9081526009602052604081208054349290611115908490611f29565b909155505073ffffffffffffffffffffffffffffffffffffffff811661114757335f9081526010602052604090204390555b6040805133815273ffffffffffffffffffffffffffffffffffffffff8416602082015234918101919091527f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc90606001610d7c565b6111a76004336115c0565b61120d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f63616e646964617465206e6f74206578697374730000000000000000000000006044820152606401610230565b611218600433611777565b50335f8181526007602090815260409182902043905590519182527f7c79e6e24ed041d1072d54523b53956f01b91b835f0490856370594d9d14470e910160405180910390a1565b6060600d8054806020026020016040519081016040528092919081815260200182805480156112c357602002820191905f5260205f20905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611298575b5050505050905090565b3373fffffffffffffffffffffffffffffffffffffffe1461134a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f736964652063616c6c206e6f7420616c6c6f77656400000000000000000000006044820152606401610230565b73121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156113a3575f80fd5b505af11580156113b5573d5f803e3d5ffd5b50505050600354600c546113c99190611f29565b4310156113d257565b5f6113dd60046115ad565b80519091505f5b818110156114c257600e5f84838151811061140157611401611e78565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205460115f85848151811061145857611458611e78565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f600354600c546114aa9190611f16565b815260208101919091526040015f20556001016113e4565b5043600c556114cf611798565b80516114e391600d91602090910190611ddc565b507fe59e3b36b5c97b419925b60c92f5a4324c993934eb9cfe5232def67c1739337c600d604051610d7c9190612081565b335f908152600a602052604090205473ffffffffffffffffffffffffffffffffffffffff16806115a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f636c61696d206e6f7420616c6c6f7765640000000000000000000000000000006044820152606401610230565b6115aa3382611614565b50565b60605f6115b983611935565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260018301602052604081205415155b90505b92915050565b5f6115ea8373ffffffffffffffffffffffffffffffffffffffff841661198e565b73ffffffffffffffffffffffffffffffffffffffff8083165f90815260106020908152604080832054600f8352818420549486168452600e835281842054601190935290832060035491949391829061166e600188611f3c565b6116789190611f16565b611683906001611f29565b81526020019081526020015f205490508281111561169f578092505b5f670de0b6b3a76400006116b38585611f3c565b73ffffffffffffffffffffffffffffffffffffffff89165f908152600b60205260409020546116e29190611ed2565b6116ec9190611f16565b73ffffffffffffffffffffffffffffffffffffffff88165f908152600f60205260409020849055905061171f8782610877565b6040805173ffffffffffffffffffffffffffffffffffffffff89168152602081018390527fbeceb521ccd2816457290c3d1cb70cc1537f14307f2d9ac26a5093a38ea40948910160405180910390a150505050505050565b5f6115ea8373ffffffffffffffffffffffffffffffffffffffff84166119da565b60605f6117a3610981565b80519091505f8167ffffffffffffffff8111156117c2576117c2612028565b6040519080825280602002602001820160405280156117eb578160200160208202803683370190505b5090505f5b828110156118745760095f85838151811061180d5761180d611e78565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205482828151811061186157611861611e78565b60209081029190910101526001016117f0565b5061188183825f54611ac4565b5f805467ffffffffffffffff81111561189c5761189c612028565b6040519080825280602002602001820160405280156118c5578160200160208202803683370190505b5090505f5b5f5481101561192c578481815181106118e5576118e5611e78565b60200260200101518282815181106118ff576118ff611e78565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526001016118ca565b50949350505050565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561198257602002820191905f5260205f20905b81548152602001906001019080831161196e575b50505050509050919050565b5f8181526001830160205260408120546119d357508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556115ed565b505f6115ed565b5f8181526001830160205260408120548015611ab4575f6119fc600183611f3c565b85549091505f90611a0f90600190611f3c565b9050808214611a6e575f865f018281548110611a2d57611a2d611e78565b905f5260205f200154905080875f018481548110611a4d57611a4d611e78565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080611a7f57611a7f6120d1565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506115ed565b5f9150506115ed565b5092915050565b82515f6001611ad46002856120fe565b611ade9190612165565b90505b5f8112611b0657611af485858386611c04565b80611afe81612184565b915050611ae1565b50815b81811015611bfd57835f81518110611b2357611b23611e78565b6020026020010151848281518110611b3d57611b3d611e78565b60200260200101511115611bf557838181518110611b5d57611b5d611e78565b6020026020010151845f81518110611b7757611b77611e78565b602002602001018181525050848181518110611b9557611b95611e78565b6020026020010151855f81518110611baf57611baf611e78565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611bf585855f86611c04565b600101611b09565b5050505050565b5f611c10836002611ed2565b611c1b906001611f29565b90505b81811015611bfd5781611c32826001611f29565b108015611c7a575083611c46826001611f29565b81518110611c5657611c56611e78565b6020026020010151848281518110611c7057611c70611e78565b6020026020010151115b15611c8d57611c8a600182611f29565b90505b838381518110611c9f57611c9f611e78565b6020026020010151848281518110611cb957611cb9611e78565b602002602001015111611bfd57838381518110611cd857611cd8611e78565b6020026020010151848281518110611cf257611cf2611e78565b6020026020010151858381518110611d0c57611d0c611e78565b60200260200101868681518110611d2557611d25611e78565b6020026020010182815250828152505050848381518110611d4857611d48611e78565b6020026020010151858281518110611d6257611d62611e78565b6020026020010151868381518110611d7c57611d7c611e78565b60200260200101878681518110611d9557611d95611e78565b73ffffffffffffffffffffffffffffffffffffffff938416602091820292909201015291169052915081611dca816002611ed2565b611dd5906001611f29565b9050611c1e565b828054828255905f5260205f20908101928215611e54579160200282015b82811115611e5457825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190611dfa565b50611e60929150611e64565b5090565b5b80821115611e60575f8155600101611e65565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820281158282048414176115ed576115ed611ea5565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f82611f2457611f24611ee9565b500490565b808201808211156115ed576115ed611ea5565b818103818111156115ed576115ed611ea5565b602080825282518282018190525f9190848201906040850190845b81811015611f9c57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611f6a565b50909695505050505050565b5f60208284031215611fb8575f80fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611fe2575f80fd5b919050565b5f60208284031215611ff7575f80fd5b6115ea82611fbf565b5f8060408385031215612011575f80fd5b61201a83611fbf565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82515f5b81811015612074576020818601810151858301520161205a565b505f920191825250919050565b602080825282548282018190525f8481528281209092916040850190845b81811015611f9c57835473ffffffffffffffffffffffffffffffffffffffff168352600193840193928501920161209f565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f8261210c5761210c611ee9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561216057612160611ea5565b500590565b8181035f831280158383131683831282161715611abd57611abd611ea5565b5f7f800000000000000000000000000000000000000000000000000000000000000082036121b4576121b4611ea5565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220fcba8ea1ad4d6b5fb44979e3302ef4c7131c8c260becbb90d014372afd04805364736f6c63430008180033" + "code": "0x6080604052600436106101b2575f3560e01c806389dc5c84116100e75780639f9d7f8111610087578063b88a802f11610062578063b88a802f146107e2578063d8ce95ab146107f6578063da0b331714610821578063db069ba51461084c575f80fd5b80639f9d7f81146107a6578063a6580de8146107ba578063a681dfec146107ce575f80fd5b8063902bdc26116100c2578063902bdc26146107155780639690293b1461074057806398ca58df146107545780639e40cdac1461077f575f80fd5b806389dc5c84146106ae5780638e1900a8146106d55780638f1b321914610700575f80fd5b80634d21e42611610152578063683dd1911161012d578063683dd191146106095780636db504e7146106245780636dd7d8ea14610665578063786255f114610678575f80fd5b80634d21e426146105b55780634ff0876a146105e057806361190533146105f5575f80fd5b80630ea6a0411161018d5780630ea6a0411461051d5780631f26f2561461056157806343c14b22146105765780634c569c251461058a575f80fd5b806303f187ea146104c157806306a49fce146104e95780630b2a85ea1461050a575f80fd5b366104bd573373121200000000000000000000000000000000000314610239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f736964652063616c6c206e6f7420616c6c6f776564000000000000000000000060448201526064015b60405180910390fd5b5f600d80548060200260200160405190810160405280929190818152602001828054801561029b57602002820191905f5260205f20905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610270575b505083519394505f925050505b818110156104bb5760095f8483815181106102c5576102c5611ea4565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e85f54670de0b6b3a764000060065f88878151811061032a5761032a611ea4565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054346103779190611efe565b6103819190611efe565b61038b9190611f42565b6103959190611f42565b61039f9190611f42565b600e5f8584815181106103b4576103b4611ea4565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546104039190611f55565b925050819055506104b383828151811061041f5761041f611ea4565b60200260200101516103e85f5460065f88878151811061044157610441611ea4565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20546103e86104909190611f68565b61049a9034611efe565b6104a49190611f42565b6104ae9190611f42565b610877565b6001016102a8565b005b5f80fd5b3480156104cc575f80fd5b506104d660025481565b6040519081526020015b60405180910390f35b3480156104f4575f80fd5b506104fd610981565b6040516104e09190611f7b565b6104bb610518366004611fd4565b610992565b348015610528575f80fd5b5061053c610537366004611fd4565b610bb0565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016104e0565b34801561056c575f80fd5b506104d6600c5481565b348015610581575f80fd5b506104bb610be5565b348015610595575f80fd5b506104d66105a4366004612013565b600e6020525f908152604090205481565b3480156105c0575f80fd5b506104d66105cf366004612013565b60086020525f908152604090205481565b3480156105eb575f80fd5b506104d660035481565b348015610600575f80fd5b506104bb610d88565b348015610614575f80fd5b506104d6670de0b6b3a764000081565b34801561062f575f80fd5b5061053c61063e366004612013565b600a6020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6104bb610673366004612013565b610e9d565b348015610683575f80fd5b506104d661069236600461202c565b601160209081525f928352604080842090915290825290205481565b3480156106b9575f80fd5b5061053c73121200000000000000000000000000000000000381565b3480156106e0575f80fd5b506104d66106ef366004612013565b600f6020525f908152604090205481565b34801561070b575f80fd5b506104d660015481565b348015610720575f80fd5b506104d661072f366004612013565b60066020525f908152604090205481565b34801561074b575f80fd5b506104bb61119c565b34801561075f575f80fd5b506104d661076e366004612013565b60106020525f908152604090205481565b34801561078a575f80fd5b5061053c73fffffffffffffffffffffffffffffffffffffffe81565b3480156107b1575f80fd5b506104fd611260565b3480156107c5575f80fd5b506104d65f5481565b3480156107d9575f80fd5b506104bb6112cd565b3480156107ed575f80fd5b506104bb611514565b348015610801575f80fd5b506104d6610810366004612013565b60096020525f908152604090205481565b34801561082c575f80fd5b506104d661083b366004612013565b60076020525f908152604090205481565b348015610857575f80fd5b506104d6610866366004612013565b600b6020525f908152604090205481565b604080515f8082526020820190925273ffffffffffffffffffffffffffffffffffffffff84169083906040516108ad9190612081565b5f6040518083038185875af1925050503d805f81146108e7576040519150601f19603f3d011682016040523d82523d5f602084013e6108ec565b606091505b505090508061097c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f736166655472616e736665724554483a20455448207472616e7366657220666160448201527f696c6564000000000000000000000000000000000000000000000000000000006064820152608401610230565b505050565b606061098d60046115ad565b905090565b6002543410156109fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e73756666696369656e7420616d6f756e74000000000000000000000000006044820152606401610230565b6103e88110610a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f696e76616c6964207261746500000000000000000000000000000000000000006044820152606401610230565b610a746004336115c0565b15610adb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f63616e64696461746520657869737473000000000000000000000000000000006044820152606401610230565b335f9081526007602052604090205415610b51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6c656674206e6f7420636c61696d6564000000000000000000000000000000006044820152606401610230565b610b5c6004336115f3565b50335f818152600660209081526040808320859055600882529182902034905590519182527feeda149c76076b34d4b9d8896c2f7efc0d33d1c7b53ea3c5db490d64613f603a91015b60405180910390a150565b600d8181548110610bbf575f80fd5b5f9182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b335f908152600a6020908152604080832054600b9092529091205473ffffffffffffffffffffffffffffffffffffffff909116908115801590610c2757505f81115b610c8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f7265766f6b65206e6f7420616c6c6f77656400000000000000000000000000006044820152606401610230565b610c973383611614565b73ffffffffffffffffffffffffffffffffffffffff82165f9081526009602052604081208054839290610ccb908490611f68565b9091555050335f818152600a6020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055600b8252808320839055600f82528083208390556010909152812055610d2d9082610877565b6040805133815273ffffffffffffffffffffffffffffffffffffffff841660208201529081018290527fb698e31a2abee5824d0d7bcfd2339aead7f9e9ae413fba50bf554ff3fa470b7b906060015b60405180910390a15050565b335f9081526007602052604090205415801590610dca5750600354610dae906002611efe565b335f90815260076020526040902054610dc79190611f55565b43115b610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7769746864726177206e6f7420616c6c6f7765640000000000000000000000006044820152606401610230565b335f81815260086020908152604080832080549084905560078352818420849055600690925282209190915590610e679082610877565b60408051338152602081018390527f142e26dcca50281d2c46d90446bfc1c9bc260cef355ce917a52f1fec7c54b5bf9101610ba5565b600154341015610f09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e73756666696369656e7420616d6f756e74000000000000000000000000006044820152606401610230565b610f146004826115c0565b610f7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f63616e646964617465206e6f7420616c6c6f77656400000000000000000000006044820152606401610230565b335f908152600a602052604090205473ffffffffffffffffffffffffffffffffffffffff908116908216811480610fc5575073ffffffffffffffffffffffffffffffffffffffff8116155b61102b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6f6e6c79206f6e652063686f69636520697320616c6c6f7765640000000000006044820152606401610230565b73ffffffffffffffffffffffffffffffffffffffff811615611056576110513382611614565b6110be565b335f818152600a6020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff88169081179091558352600e825280832054938352600f9091529020555b335f908152600b6020526040812080543492906110dc908490611f55565b909155505073ffffffffffffffffffffffffffffffffffffffff82165f9081526009602052604081208054349290611115908490611f55565b909155505073ffffffffffffffffffffffffffffffffffffffff811661114757335f9081526010602052604090204390555b6040805133815273ffffffffffffffffffffffffffffffffffffffff8416602082015234918101919091527f66a9138482c99e9baf08860110ef332cc0c23b4a199a53593d8db0fc8f96fbfc90606001610d7c565b6111a76004336115c0565b61120d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f63616e646964617465206e6f74206578697374730000000000000000000000006044820152606401610230565b6112186004336117a3565b50335f8181526007602090815260409182902043905590519182527f7c79e6e24ed041d1072d54523b53956f01b91b835f0490856370594d9d14470e910160405180910390a1565b6060600d8054806020026020016040519081016040528092919081815260200182805480156112c357602002820191905f5260205f20905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611298575b5050505050905090565b3373fffffffffffffffffffffffffffffffffffffffe1461134a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f736964652063616c6c206e6f7420616c6c6f77656400000000000000000000006044820152606401610230565b73121200000000000000000000000000000000000373ffffffffffffffffffffffffffffffffffffffff16633ccfd60b6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156113a3575f80fd5b505af11580156113b5573d5f803e3d5ffd5b50505050600354600c546113c99190611f55565b4310156113d257565b5f6113dd60046115ad565b80519091505f5b818110156114c257600e5f84838151811061140157611401611ea4565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205460115f85848151811061145857611458611ea4565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f600354600c546114aa9190611f42565b815260208101919091526040015f20556001016113e4565b5043600c556114cf6117c4565b80516114e391600d91602090910190611e08565b507fe59e3b36b5c97b419925b60c92f5a4324c993934eb9cfe5232def67c1739337c600d604051610d7c91906120ad565b335f908152600a602052604090205473ffffffffffffffffffffffffffffffffffffffff16806115a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f636c61696d206e6f7420616c6c6f7765640000000000000000000000000000006044820152606401610230565b6115aa3382611614565b50565b60605f6115b983611961565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81165f90815260018301602052604081205415155b90505b92915050565b5f6115ea8373ffffffffffffffffffffffffffffffffffffffff84166119ba565b73ffffffffffffffffffffffffffffffffffffffff8083165f90815260106020908152604080832054600f8352818420549486168452600e90925290912054600c549192918310611666575050505050565b73ffffffffffffffffffffffffffffffffffffffff84165f908152601160205260408120600354829061169a600188611f68565b6116a49190611f42565b6116af906001611f55565b81526020019081526020015f20549050828111156116cb578092505b5f670de0b6b3a76400006116df8585611f68565b73ffffffffffffffffffffffffffffffffffffffff89165f908152600b602052604090205461170e9190611efe565b6117189190611f42565b73ffffffffffffffffffffffffffffffffffffffff88165f908152600f60205260409020849055905061174b8782610877565b6040805173ffffffffffffffffffffffffffffffffffffffff89168152602081018390527fbeceb521ccd2816457290c3d1cb70cc1537f14307f2d9ac26a5093a38ea40948910160405180910390a150505050505050565b5f6115ea8373ffffffffffffffffffffffffffffffffffffffff8416611a06565b60605f6117cf610981565b80519091505f8167ffffffffffffffff8111156117ee576117ee612054565b604051908082528060200260200182016040528015611817578160200160208202803683370190505b5090505f5b828110156118a05760095f85838151811061183957611839611ea4565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205482828151811061188d5761188d611ea4565b602090810291909101015260010161181c565b506118ad83825f54611af0565b5f805467ffffffffffffffff8111156118c8576118c8612054565b6040519080825280602002602001820160405280156118f1578160200160208202803683370190505b5090505f5b5f548110156119585784818151811061191157611911611ea4565b602002602001015182828151811061192b5761192b611ea4565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526001016118f6565b50949350505050565b6060815f018054806020026020016040519081016040528092919081815260200182805480156119ae57602002820191905f5260205f20905b81548152602001906001019080831161199a575b50505050509050919050565b5f8181526001830160205260408120546119ff57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556115ed565b505f6115ed565b5f8181526001830160205260408120548015611ae0575f611a28600183611f68565b85549091505f90611a3b90600190611f68565b9050808214611a9a575f865f018281548110611a5957611a59611ea4565b905f5260205f200154905080875f018481548110611a7957611a79611ea4565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080611aab57611aab6120fd565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506115ed565b5f9150506115ed565b5092915050565b82515f6001611b0060028561212a565b611b0a9190612191565b90505b5f8112611b3257611b2085858386611c30565b80611b2a816121b0565b915050611b0d565b50815b81811015611c2957835f81518110611b4f57611b4f611ea4565b6020026020010151848281518110611b6957611b69611ea4565b60200260200101511115611c2157838181518110611b8957611b89611ea4565b6020026020010151845f81518110611ba357611ba3611ea4565b602002602001018181525050848181518110611bc157611bc1611ea4565b6020026020010151855f81518110611bdb57611bdb611ea4565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611c2185855f86611c30565b600101611b35565b5050505050565b5f611c3c836002611efe565b611c47906001611f55565b90505b81811015611c295781611c5e826001611f55565b108015611ca6575083611c72826001611f55565b81518110611c8257611c82611ea4565b6020026020010151848281518110611c9c57611c9c611ea4565b6020026020010151115b15611cb957611cb6600182611f55565b90505b838381518110611ccb57611ccb611ea4565b6020026020010151848281518110611ce557611ce5611ea4565b602002602001015111611c2957838381518110611d0457611d04611ea4565b6020026020010151848281518110611d1e57611d1e611ea4565b6020026020010151858381518110611d3857611d38611ea4565b60200260200101868681518110611d5157611d51611ea4565b6020026020010182815250828152505050848381518110611d7457611d74611ea4565b6020026020010151858281518110611d8e57611d8e611ea4565b6020026020010151868381518110611da857611da8611ea4565b60200260200101878681518110611dc157611dc1611ea4565b73ffffffffffffffffffffffffffffffffffffffff938416602091820292909201015291169052915081611df6816002611efe565b611e01906001611f55565b9050611c4a565b828054828255905f5260205f20908101928215611e80579160200282015b82811115611e8057825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190611e26565b50611e8c929150611e90565b5090565b5b80821115611e8c575f8155600101611e91565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820281158282048414176115ed576115ed611ed1565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f82611f5057611f50611f15565b500490565b808201808211156115ed576115ed611ed1565b818103818111156115ed576115ed611ed1565b602080825282518282018190525f9190848201906040850190845b81811015611fc857835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611f96565b50909695505050505050565b5f60208284031215611fe4575f80fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461200e575f80fd5b919050565b5f60208284031215612023575f80fd5b6115ea82611feb565b5f806040838503121561203d575f80fd5b61204683611feb565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82515f5b818110156120a05760208186018101518583015201612086565b505f920191825250919050565b602080825282548282018190525f8481528281209092916040850190845b81811015611fc857835473ffffffffffffffffffffffffffffffffffffffff16835260019384019392850192016120cb565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b5f8261213857612138611f15565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561218c5761218c611ed1565b500590565b8181035f831280158383131683831282161715611ae957611ae9611ed1565b5f7f800000000000000000000000000000000000000000000000000000000000000082036121e0576121e0611ed1565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220be030c978d41bf189a496211a49a065d8172632668166ae46e11aefab15d3ab864736f6c63430008180033" }, "0x1212100000000000000000000000000000000002": { "balance": "0",