contract MinGasPriceVote {
uint constant MinGasPriceDeltaRate = 5;
uint constant MinGasPriceUpperBound = 500000000000; //500gwei
uint constant MinGasPriceLowerBound = 10000000; //0.01gwei
uint constant DefaultProposalDuration = 60 * 60 * 24; //24hour
uint endVotingTime public;
mapping(address => uint) voteMap public;
function proposal(uint target) external {
require(isValidator(msg.sender), "not-a-validator");
uint64 votingPower = getVotingPower(msg.sender);
require(votingPower != 0, "inactive-validator");
require(endVotingTime == 0, "is-still-voting");
checkTarget(minGasPrice, target);
endVotingTime = block.timestamp + DefaultProposalDuration;
voteMap[msg.sender] = (target<<64) + uint(votingPower);
function checkTarget(uint lastMinGasPrice, uint target) private {
require(MinGasPriceLowerBound < target, "target-too-small");
require(target < MinGasPriceUpperBound, "target-too-large");
if(lastMinGasPrice != 0) {
require(lastMinGasPrice/MinGasPriceDeltaRate <= target &&
target <= lastMinGasPrice*MinGasPriceDeltaRate, "target-outof-range");
function addVoter(address voter) private {
for(uint i=0; i<voters.length; i++) {
if(voters[i] == voter) return;
function vote(uint target) external {
require(isValidator(msg.sender), "not-a-validator");
uint64 votingPower = getVotingPower(msg.sender);
require(votingPower != 0, "inactive-validator");
require(endVotingTime != 0, "not-in-voting");
require(block.timestamp < endVotingTime, "voting-finished");
checkTarget(minGasPrice, target);
voteMap[msg.sender] = (target<<64) + uint(votingPower);
function executeProposal() external {
require(endVotingTime != 0, "not-in-voting");
require(endVotingTime < block.timestamp, "voting-not-finished");
minGasPrice = calculateMinGasPrice();
uint index = voters.length-1;
address voter = voters[index];
function calculateMinGasPrice() private returns (uint) {
uint[] memory targets = new uint[](voters.length);
for(uint i=0; i<voters.length; i++) {
address voter = voters[i];
uint vote = voteMap[voter];
(uint target, uint votingPower) = (uint(vote>>64), uint(uint64(vote)));
sumTargets += target*votingPower;
uint t1 = calculateMeidan(targets);
uint t2 = sumTargets / sumPower;
function calculateMeidan(uint[] memory targets) private pure returns (uint) {
uint index = targets.length/2; 4/2=2
if(index*2 == targets.length) {
returns (targets[index-1] + targets[index]) / 2
function sort(uint[] memory arr) private pure {
quickSort(arr, 0, arr.length - 1);
function quickSort(uint[] memory arr, uint left, uint right) private pure {
uint p = arr[(left + right) / 2]; // p = the pivot element
while (arr[j] > p) --j; // arr[j] > p means p still to the left, so j > 0
(arr[i], arr[j]) = (arr[j], arr[i]);
// Note --j was only done when a[j] > p. So we know: a[j] == p, a[<j] <= p, a[>j] > p
quickSort(arr, left, j - 1); // j > left, so j > 0
quickSort(arr, j + 1, right);