Contract Overview
Balance:
0 FTM
My Name Tag:
Not Available
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0x09F44D7F15dd65529CF261c5ea8364e09A51d7C3
Contract Name:
NetworkParameterProposalFactory
Compiler Version
v0.5.17+commit.d19bba13
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.5.0; library Decimal { // unit is used for decimals, e.g. 0.123456 function unit() internal pure returns (uint256) { return 1e18; } }
pragma solidity >=0.4.24 <0.7.0; /** * @title Initializable * * @dev Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. */ contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool isTopLevelCall = !initializing; if (isTopLevelCall) { initializing = true; initialized = true; } _; if (isTopLevelCall) { initializing = false; } } /// @dev Returns true if and only if the function is running in the constructor function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. address self = address(this); uint256 cs; assembly { cs := extcodesize(self) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; }
pragma solidity ^0.5.0; import "./Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. */ contract ReentrancyGuard is Initializable { // counter to allow mutex lock with only one SSTORE operation uint256 private _guardCounter; function initialize() internal initializer { // The counter starts at one to prevent changing it from zero to a non-zero // value, which is a more expensive operation. _guardCounter = 1; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { _guardCounter += 1; uint256 localCounter = _guardCounter; _; require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call"); } uint256[50] private ______gap; }
pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
pragma solidity ^0.5.0; import "../common/SafeMath.sol"; import "../common/Decimal.sol"; contract StatusConstants { enum Status { INITIAL, RESOLVED, FAILED } // bit map uint256 constant STATUS_INITIAL = 0; uint256 constant STATUS_RESOLVED = 1; uint256 constant STATUS_FAILED = 1 << 1; uint256 constant STATUS_CANCELED = 1 << 2; uint256 constant STATUS_EXECUTION_EXPIRED = 1 << 3; function statusInitial() internal pure returns (uint256) { return STATUS_INITIAL; } function statusExecutionExpired() internal pure returns (uint256) { return STATUS_EXECUTION_EXPIRED; } function statusFailed() internal pure returns (uint256) { return STATUS_FAILED; } function statusCanceled() internal pure returns (uint256) { return STATUS_CANCELED; } function statusResolved() internal pure returns (uint256) { return STATUS_RESOLVED; } function isInitialStatus(uint256 status) internal pure returns (bool) { return status == STATUS_INITIAL; } // task assignments uint256 constant TASK_VOTING = 1; } contract Constants is StatusConstants { using SafeMath for uint256; function minVotesAbsolute(uint256 totalWeight, uint256 minVotesRatio) public pure returns (uint256) { return totalWeight * minVotesRatio / Decimal.unit(); } function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) { bytes memory bytesArray = new bytes(32); for (uint256 i; i < 32; i++) { bytesArray[i] = _bytes32[i]; } return string(bytesArray); } }
pragma solidity ^0.5.0; import "../common/ReentrancyGuard.sol"; import "../common/SafeMath.sol"; import "../model/Governable.sol"; import "../proposal/base/IProposal.sol"; import "../verifiers/IProposalVerifier.sol"; import "../proposal/SoftwareUpgradeProposal.sol"; import "./Proposal.sol"; import "./Constants.sol"; import "./GovernanceSettings.sol"; import "./LRC.sol"; import "../version/Version.sol"; import "../votebook/votebook.sol"; contract Governance is Initializable, ReentrancyGuard, GovernanceSettings, Version { using SafeMath for uint256; using LRC for LRC.Option; struct Vote { uint256 weight; uint256[] choices; } struct ProposalState { Proposal.Parameters params; // voting state mapping(uint256 => LRC.Option) options; uint256 winnerOptionID; uint256 votes; // total weight of votes uint256 status; } struct Task { bool active; uint256 assignment; uint256 proposalID; } Governable governableContract; IProposalVerifier proposalVerifier; uint256 public lastProposalID; Task[] tasks; mapping(uint256 => ProposalState) proposals; mapping(address => mapping(uint256 => uint256)) public overriddenWeight; // voter address, proposalID -> weight mapping(address => mapping(address => mapping(uint256 => Vote))) _votes; // voter, delegationReceiver, proposalID -> Vote VotesBookKeeper votebook; event ProposalCreated(uint256 proposalID); event ProposalResolved(uint256 proposalID); event ProposalRejected(uint256 proposalID); event ProposalCanceled(uint256 proposalID); event ProposalExecutionExpired(uint256 proposalID); event TasksHandled(uint256 startIdx, uint256 endIdx, uint256 handled); event TasksErased(uint256 quantity); event VoteWeightOverridden(address voter, uint256 diff); event VoteWeightUnOverridden(address voter, uint256 diff); event Voted(address voter, address delegatedTo, uint256 proposalID, uint256[] choices, uint256 weight); event VoteCanceled(address voter, address delegatedTo, uint256 proposalID); function initialize(address _governableContract, address _proposalVerifier, address _votebook) public initializer { ReentrancyGuard.initialize(); governableContract = Governable(_governableContract); proposalVerifier = IProposalVerifier(_proposalVerifier); votebook = VotesBookKeeper(_votebook); } function proposalParams(uint256 proposalID) public view returns (uint256 pType, Proposal.ExecType executable, uint256 minVotes, uint256 minAgreement, uint256[] memory opinionScales, bytes32[] memory options, address proposalContract, uint256 votingStartTime, uint256 votingMinEndTime, uint256 votingMaxEndTime) { Proposal.Parameters memory p = proposals[proposalID].params; return (p.pType, p.executable, p.minVotes, p.minAgreement, p.opinionScales, p.options, p.proposalContract, p.deadlines.votingStartTime, p.deadlines.votingMinEndTime, p.deadlines.votingMaxEndTime); } function proposalOptionState(uint256 proposalID, uint256 optionID) public view returns (uint256 votes, uint256 agreementRatio, uint256 agreement) { ProposalState storage prop = proposals[proposalID]; LRC.Option storage opt = prop.options[optionID]; return (opt.votes, LRC.agreementRatio(opt), opt.agreement); } function proposalState(uint256 proposalID) public view returns (uint256 winnerOptionID, uint256 votes, uint256 status) { ProposalState memory p = proposals[proposalID]; return (p.winnerOptionID, p.votes, p.status); } function getVote(address from, address delegatedTo, uint256 proposalID) public view returns (uint256 weight, uint256[] memory choices) { Vote memory v = _votes[from][delegatedTo][proposalID]; return (v.weight, v.choices); } function tasksCount() public view returns (uint256) { return (tasks.length); } function getTask(uint256 i) public view returns (bool active, uint256 assignment, uint256 proposalID) { Task memory t = tasks[i]; return (t.active, t.assignment, t.proposalID); } function vote(address delegatedTo, uint256 proposalID, uint256[] calldata choices) nonReentrant external { if (delegatedTo == address(0)) { delegatedTo = msg.sender; } ProposalState storage prop = proposals[proposalID]; require(prop.params.proposalContract != address(0), "proposal with a given ID doesnt exist"); require(isInitialStatus(prop.status), "proposal isn't active"); require(block.timestamp >= prop.params.deadlines.votingStartTime, "proposal voting has't begun"); require(_votes[msg.sender][delegatedTo][proposalID].weight == 0, "vote already exists"); require(choices.length == prop.params.options.length, "wrong number of choices"); uint256 weight = _processNewVote(proposalID, msg.sender, delegatedTo, choices); require(weight != 0, "zero weight"); } function createProposal(address proposalContract) nonReentrant external payable { require(msg.value == proposalFee(), "paid proposal fee is wrong"); lastProposalID++; _createProposal(lastProposalID, proposalContract); addTasks(lastProposalID); // burn a non-reward part of the proposal fee burn(proposalBurntFee()); emit ProposalCreated(lastProposalID); } function _createProposal(uint256 proposalID, address proposalContract) internal { require(proposalContract != address(0), "empty proposal address"); IProposal p = IProposal(proposalContract); // capture the parameters once to ensure that contract will not return different values uint256 pType = p.pType(); Proposal.ExecType executable = p.executable(); uint256 minVotes = p.minVotes(); uint256 minAgreement = p.minAgreement(); uint256[] memory opinionScales = p.opinionScales(); uint256 votingStartTime = p.votingStartTime(); uint256 votingMinEndTime = p.votingMinEndTime(); uint256 votingMaxEndTime = p.votingMaxEndTime(); bytes32[] memory options = p.options(); // check the parameters and contract require(options.length != 0, "proposal options are empty - nothing to vote for"); require(options.length <= maxOptions(), "too many options"); bool ok; ok = proposalVerifier.verifyProposalParams(pType, executable, minVotes, minAgreement, opinionScales, votingStartTime, votingMinEndTime, votingMaxEndTime); require(ok, "proposal parameters failed verification"); ok = proposalVerifier.verifyProposalContract(pType, proposalContract); require(ok, "proposal contract failed verification"); // save the parameters ProposalState storage prop = proposals[proposalID]; prop.params.pType = pType; prop.params.executable = executable; prop.params.minVotes = minVotes; prop.params.minAgreement = minAgreement; prop.params.opinionScales = opinionScales; prop.params.proposalContract = proposalContract; prop.params.deadlines.votingStartTime = votingStartTime; prop.params.deadlines.votingMinEndTime = votingMinEndTime; prop.params.deadlines.votingMaxEndTime = votingMaxEndTime; prop.params.options = options; } // cancelProposal cancels the proposal if no one managed to vote yet // must be sent from the proposal contract function cancelProposal(uint256 proposalID) nonReentrant external { ProposalState storage prop = proposals[proposalID]; require(prop.params.proposalContract != address(0), "proposal with a given ID doesnt exist"); require(isInitialStatus(prop.status), "proposal isn't active"); require(prop.votes == 0, "voting has already begun"); require(msg.sender == prop.params.proposalContract, "must be sent from the proposal contract"); prop.status = statusCanceled(); emit ProposalCanceled(proposalID); } // handleTasks triggers proposal deadlines processing for a specified range of tasks function handleTasks(uint256 startIdx, uint256 quantity) nonReentrant external { uint256 handled = 0; uint256 i; for (i = startIdx; i < tasks.length && i < startIdx + quantity; i++) { if (handleTask(i)) { handled += 1; } } require(handled != 0, "no tasks handled"); emit TasksHandled(startIdx, i, handled); // reward the sender msg.sender.transfer(handled.mul(taskHandlingReward())); } // tasksCleanup erases inactive (handled) tasks backwards until an active task is met function tasksCleanup(uint256 quantity) nonReentrant external { uint256 erased; for (erased = 0; tasks.length > 0 && erased < quantity; erased++) { if (!tasks[tasks.length - 1].active) { tasks.length--; } else { break; // stop when first active task was met } } require(erased > 0, "no tasks erased"); emit TasksErased(erased); // reward the sender msg.sender.transfer(erased.mul(taskErasingReward())); } // handleTask calls handleTaskAssignments and marks task as inactive if it was handled function handleTask(uint256 taskIdx) internal returns (bool handled) { require(taskIdx < tasks.length, "incorrect task index"); Task storage task = tasks[taskIdx]; if (!task.active) { return false; } handled = handleTaskAssignments(tasks[taskIdx].proposalID, task.assignment); if (handled) { task.active = false; } return handled; } // handleTaskAssignments iterates through assignment types and calls a specific handler function handleTaskAssignments(uint256 proposalID, uint256 assignment) internal returns (bool handled) { ProposalState storage prop = proposals[proposalID]; if (!isInitialStatus(prop.status)) { // deactivate all tasks for non-active proposals return true; } if (assignment == TASK_VOTING) { return handleVotingTask(proposalID, prop); } return false; } // handleVotingTask handles only TASK_VOTING function handleVotingTask(uint256 proposalID, ProposalState storage prop) internal returns (bool handled) { uint256 minVotesAbs = minVotesAbsolute(governableContract.getTotalWeight(), prop.params.minVotes); bool must = block.timestamp >= prop.params.deadlines.votingMaxEndTime; bool may = block.timestamp >= prop.params.deadlines.votingMinEndTime && prop.votes >= minVotesAbs; if (!must && !may) { return false; } (bool proposalResolved, uint256 winnerID) = _calculateVotingTally(prop); if (proposalResolved) { (bool ok, bool expired) = executeProposal(prop, winnerID); if (!ok) { return false; } if (!expired) { prop.status = statusResolved(); prop.winnerOptionID = winnerID; emit ProposalResolved(proposalID); } else { prop.status = statusExecutionExpired(); emit ProposalExecutionExpired(proposalID); } } else { prop.status = statusFailed(); emit ProposalRejected(proposalID); } return true; } function executeProposal(ProposalState storage prop, uint256 winnerOptionID) internal returns (bool, bool) { bool executable = prop.params.executable == Proposal.ExecType.CALL || prop.params.executable == Proposal.ExecType.DELEGATECALL; if (!executable) { return (true, false); } bool executionExpired = block.timestamp > prop.params.deadlines.votingMaxEndTime + maxExecutionPeriod(); if (executionExpired) { // protection against proposals which revert or consume too much gas return (true, true); } address propAddr = prop.params.proposalContract; bool success; bytes memory result; if (prop.params.executable == Proposal.ExecType.CALL) { (success, result) = propAddr.call(abi.encodeWithSignature("execute_call(uint256)", winnerOptionID)); } else { (success, result) = propAddr.delegatecall(abi.encodeWithSignature("execute_delegatecall(address,uint256)", propAddr, winnerOptionID)); } result; return (success, false); } function _calculateVotingTally(ProposalState storage prop) internal view returns (bool, uint256) { uint256 minVotesAbs = minVotesAbsolute(governableContract.getTotalWeight(), prop.params.minVotes); uint256 mostAgreement = 0; uint256 winnerID = prop.params.options.length; if (prop.votes < minVotesAbs) { return (false, winnerID); } for (uint256 i = 0; i < prop.params.options.length; i++) { uint256 optionID = i; uint256 agreement = LRC.agreementRatio(prop.options[optionID]); if (agreement < prop.params.minAgreement) { // critical resistance against this option continue; } if (mostAgreement == 0 || agreement > mostAgreement) { mostAgreement = agreement; winnerID = i; } } return (winnerID != prop.params.options.length, winnerID); } // calculateVotingTally calculates the voting tally and returns {is finished, won option ID, total weight of votes} function calculateVotingTally(uint256 proposalID) external view returns (bool proposalResolved, uint256 winnerID, uint256 votes) { ProposalState storage prop = proposals[proposalID]; (proposalResolved, winnerID) = _calculateVotingTally(prop); return (proposalResolved, winnerID, prop.votes); } function cancelVote(address delegatedTo, uint256 proposalID) nonReentrant external { if (delegatedTo == address(0)) { delegatedTo = msg.sender; } Vote memory v = _votes[msg.sender][delegatedTo][proposalID]; require(v.weight != 0, "doesn't exist"); require(isInitialStatus(proposals[proposalID].status), "proposal isn't active"); _cancelVote(msg.sender, delegatedTo, proposalID); } function _cancelVote(address voter, address delegatedTo, uint256 proposalID) internal { Vote storage v = _votes[voter][delegatedTo][proposalID]; if (v.weight == 0) { return; } if (voter != delegatedTo) { unOverrideDelegationWeight(delegatedTo, proposalID, v.weight); } removeChoicesFromProp(proposalID, v.choices, v.weight); delete _votes[voter][delegatedTo][proposalID]; if (address(votebook) != address(0)) { votebook.onVoteCanceled(voter, delegatedTo, proposalID); } emit VoteCanceled(voter, delegatedTo, proposalID); } function makeVote(uint256 proposalID, address voter, address delegatedTo, uint256[] memory choices, uint256 weight) internal { _votes[voter][delegatedTo][proposalID] = Vote(weight, choices); addChoicesToProp(proposalID, choices, weight); if (address(votebook) != address(0)) { votebook.onVoted(voter, delegatedTo, proposalID); } emit Voted(voter, delegatedTo, proposalID, choices, weight); } function _processNewVote(uint256 proposalID, address voterAddr, address delegatedTo, uint256[] memory choices) internal returns (uint256) { if (delegatedTo == voterAddr) { // voter isn't a delegator uint256 weight = governableContract.getReceivedWeight(voterAddr); uint256 overridden = overriddenWeight[voterAddr][proposalID]; if (weight > overridden) { weight -= overridden; } else { weight = 0; } if (weight == 0) { return 0; } makeVote(proposalID, voterAddr, voterAddr, choices, weight); return weight; } else { if (_votes[delegatedTo][delegatedTo][proposalID].choices.length > 0) { // recount vote from delegatedTo // Needed only in a case if delegatedTo's received weight has changed without calling recountVote _recountVote(delegatedTo, delegatedTo, proposalID); } // votes through one of delegations, overrides previous vote of "delegatedTo" (if any) uint256 delegatedWeight = governableContract.getWeight(voterAddr, delegatedTo); // reduce weight of vote of "delegatedTo" (current vote or any future vote) overrideDelegationWeight(delegatedTo, proposalID, delegatedWeight); if (delegatedWeight == 0) { return 0; } // make own vote makeVote(proposalID, voterAddr, delegatedTo, choices, delegatedWeight); return delegatedWeight; } } function recountVote(address voterAddr, address delegatedTo, uint256 proposalID) nonReentrant external { Vote storage v = _votes[voterAddr][delegatedTo][proposalID]; Vote storage vSuper = _votes[delegatedTo][delegatedTo][proposalID]; require(v.choices.length > 0, "doesn't exist"); require(isInitialStatus(proposals[proposalID].status), "proposal isn't active"); uint256 beforeSelf = v.weight; uint256 beforeSuper = vSuper.weight; _recountVote(voterAddr, delegatedTo, proposalID); uint256 afterSelf = v.weight; uint256 afterSuper = vSuper.weight; // check that some weight has changed due to recounting require(beforeSelf != afterSelf || beforeSuper != afterSuper, "nothing changed"); } function _recountVote(address voterAddr, address delegatedTo, uint256 proposalID) internal returns (uint256) { uint256[] memory origChoices = _votes[voterAddr][delegatedTo][proposalID].choices; // cancel previous vote _cancelVote(voterAddr, delegatedTo, proposalID); // re-make vote return _processNewVote(proposalID, voterAddr, delegatedTo, origChoices); } function overrideDelegationWeight(address delegatedTo, uint256 proposalID, uint256 weight) internal { uint256 overridden = overriddenWeight[delegatedTo][proposalID]; overridden = overridden.add(weight); overriddenWeight[delegatedTo][proposalID] = overridden; Vote storage v = _votes[delegatedTo][delegatedTo][proposalID]; if (v.choices.length > 0) { v.weight = v.weight.sub(weight); removeChoicesFromProp(proposalID, v.choices, weight); } emit VoteWeightOverridden(delegatedTo, weight); } function unOverrideDelegationWeight(address delegatedTo, uint256 proposalID, uint256 weight) internal { uint256 overridden = overriddenWeight[delegatedTo][proposalID]; overridden = overridden.sub(weight); overriddenWeight[delegatedTo][proposalID] = overridden; Vote storage v = _votes[delegatedTo][delegatedTo][proposalID]; if (v.choices.length > 0) { v.weight = v.weight.add(weight); addChoicesToProp(proposalID, v.choices, weight); } emit VoteWeightUnOverridden(delegatedTo, weight); } function addChoicesToProp(uint256 proposalID, uint256[] memory choices, uint256 weight) internal { ProposalState storage prop = proposals[proposalID]; prop.votes = prop.votes.add(weight); for (uint256 i = 0; i < prop.params.options.length; i++) { prop.options[i].addVote(choices[i], weight, prop.params.opinionScales); } } function removeChoicesFromProp(uint256 proposalID, uint256[] memory choices, uint256 weight) internal { ProposalState storage prop = proposals[proposalID]; prop.votes = prop.votes.sub(weight); for (uint256 i = 0; i < prop.params.options.length; i++) { prop.options[i].removeVote(choices[i], weight, prop.params.opinionScales); } } function addTasks(uint256 proposalID) internal { tasks.push(Task(true, TASK_VOTING, proposalID)); } function burn(uint256 amount) internal { address(0).transfer(amount); } function sanitizeWinnerID(uint256 proposalID) external { ProposalState storage prop = proposals[proposalID]; require(prop.status == STATUS_RESOLVED, "proposal isn't resolved"); require(prop.params.executable == Proposal.ExecType.NONE, "proposal is executable"); require(prop.winnerOptionID == 0, "winner ID is correct"); (, prop.winnerOptionID) = _calculateVotingTally(prop); } function upgrade(address _votebook) external { require(address(votebook) == address(0), "already set"); votebook = VotesBookKeeper(_votebook); // erase leftovers from upgradeability proxy assembly { sstore(0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103, 0) sstore(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc, 0) } } }
pragma solidity ^0.5.0; import "../common/Decimal.sol"; import "../common/SafeMath.sol"; import "../model/Governable.sol"; import "../proposal/SoftwareUpgradeProposal.sol"; import "./Constants.sol"; /** * @dev Various constants for governance governance settings */ contract GovernanceSettings is Constants { uint256 constant _proposalFee = _proposalBurntFee + _taskHandlingReward + _taskErasingReward; uint256 constant _proposalBurntFee = 50 * 1e18; uint256 constant _taskHandlingReward = 40 * 1e18; uint256 constant _taskErasingReward = 10 * 1e18; uint256 constant _maxOptions = 10; uint256 constant _maxExecutionPeriod = 3 days; // @dev proposalFee is the fee for a proposal function proposalFee() public pure returns (uint256) { return _proposalFee; } // @dev proposalBurntFee is the burnt part of fee for a proposal function proposalBurntFee() public pure returns (uint256) { return _proposalBurntFee; } // @dev taskHandlingReward is a reward for handling each task function taskHandlingReward() public pure returns (uint256) { return _taskHandlingReward; } // @dev taskErasingReward is a reward for erasing each task function taskErasingReward() public pure returns (uint256) { return _taskErasingReward; } // @dev maxOptions maximum number of options to choose function maxOptions() public pure returns (uint256) { return _maxOptions; } // maxExecutionPeriod is maximum time for which proposal is executable after maximum voting end date function maxExecutionPeriod() public pure returns (uint256) { return _maxExecutionPeriod; } }
pragma solidity ^0.5.0; import "../common/Decimal.sol"; import "../common/SafeMath.sol"; /** * @dev LRC implements the "least resistant consensus" paper. More detailed description can be found in Fantom's docs. */ library LRC { using SafeMath for uint256; struct Option { uint256 votes; uint256 agreement; } // agreementRatio is a ratio of option agreement (higher -> option is less supported) function agreementRatio(Option storage self) internal view returns (uint256) { if (self.votes == 0) { // avoid division by zero return 0; } return self.agreement.mul(Decimal.unit()).div(self.votes); } function maxAgreementScale(uint256[] storage opinionScales) internal view returns (uint256) { return opinionScales[opinionScales.length - 1]; } function addVote(Option storage self, uint256 opinionID, uint256 weight, uint256[] storage opinionScales) internal { require(opinionID < opinionScales.length, "wrong opinion ID"); uint256 scale = opinionScales[opinionID]; self.votes = self.votes.add(weight); self.agreement = self.agreement.add(weight.mul(scale).div(maxAgreementScale(opinionScales))); } function removeVote(Option storage self, uint256 opinionID, uint256 weight, uint256[] storage opinionScales) internal { require(opinionID < opinionScales.length, "wrong opinion ID"); uint256 scale = opinionScales[opinionID]; self.votes = self.votes.sub(weight); self.agreement = self.agreement.sub(weight.mul(scale).div(maxAgreementScale(opinionScales))); } }
pragma solidity ^0.5.0; import "../proposal/base/IProposal.sol"; library Proposal { struct Timeline { uint256 votingStartTime; // date when the voting starts uint256 votingMinEndTime; // date of earliest possible voting end uint256 votingMaxEndTime; // date of latest possible voting end } enum ExecType { NONE, CALL, DELEGATECALL } struct Parameters { uint256 pType; // type of proposal (e.g. plaintext, software upgrade) ExecType executable; // proposal execution type when proposal gets resolved uint256 minVotes; // min. quorum (ratio) // minAgreement is the minimum acceptable ratio of agreement for an option. // It's guaranteed not to win otherwise. uint256 minAgreement; // min. agreement threshold for options (ratio) uint256[] opinionScales; address proposalContract; // contract which stores the proposal data and executes its logic bytes32[] options; Timeline deadlines; } }
pragma solidity ^0.5.0; /** * @dev Governable defines the main interface for all governable items */ interface Governable { // Gets the total weight of voters function getTotalWeight() external view returns (uint256); // Gets the received delegated weight function getReceivedWeight(address addr) external view returns (uint256); // Gets the voting weight which is delegated from the specified address to the specified address function getWeight(address from, address to) external view returns (uint256); }
pragma solidity ^0.5.0; import "../common/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be aplied to your functions to restrict their use to * the owner. */ contract Ownable is Initializable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function initialize(address sender) internal initializer { _owner = sender; emit OwnershipTransferred(address(0), _owner); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return msg.sender == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * > Note: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } uint256[50] private ______gap; }
pragma solidity ^0.5.0; import "../common/SafeMath.sol"; import "../governance/Governance.sol"; import "../proposal/NetworkParameterProposal.sol"; import "../verifiers/ScopedVerifier.sol"; contract NetworkParameterProposalFactory is ScopedVerifier { using SafeMath for uint256; Governance internal gov; address internal constsAddress; address public lastNetworkProposal; constructor(address _governance, address _constsAddress) public { gov = Governance(_governance); constsAddress = _constsAddress; } function create( string memory __description, uint8 __methodID, uint256[] memory __optionVals, uint256 __minVotes, uint256 __minAgreement, uint256 __start, uint256 __minEnd, uint256 __maxEnd ) public payable { NetworkParameterProposal proposal = new NetworkParameterProposal( __description, __methodID, __optionVals, constsAddress, __minVotes, __minAgreement, __start, __minEnd, __maxEnd, address(0)); proposal.transferOwnership(msg.sender); lastNetworkProposal = address(proposal); unlockedFor = address(proposal); gov.createProposal.value(msg.value)(address(proposal)); unlockedFor = address(0); } }
pragma solidity ^0.5.0; import "../../common/SafeMath.sol"; import "./IProposal.sol"; import "../../verifiers/IProposalVerifier.sol"; import "../../governance/Proposal.sol"; /** * @dev A base for any proposal */ contract BaseProposal is IProposal { using SafeMath for uint256; string _name; string _description; bytes32[] _options; uint256 _minVotes; uint256 _minAgreement; uint256[] _opinionScales; uint256 _start; uint256 _minEnd; uint256 _maxEnd; // verifyProposalParams passes proposal parameters to a given verifier function verifyProposalParams(address verifier) public view returns (bool) { IProposalVerifier proposalVerifier = IProposalVerifier(verifier); return proposalVerifier.verifyProposalParams(pType(), executable(), minVotes(), minAgreement(), opinionScales(), votingStartTime(), votingMinEndTime(), votingMaxEndTime()); } function pType() public view returns (uint256) { require(false, "must be overridden"); return uint256(StdProposalTypes.NOT_INIT); } function executable() public view returns (Proposal.ExecType) { require(false, "must be overridden"); return Proposal.ExecType.NONE; } function minVotes() public view returns (uint256) { return _minVotes; } function minAgreement() public view returns (uint256) { return _minAgreement; } function opinionScales() public view returns (uint256[] memory) { return _opinionScales; } function options() public view returns (bytes32[] memory) { return _options; } function votingStartTime() public view returns (uint256) { return block.timestamp + _start; } function votingMinEndTime() public view returns (uint256) { return votingStartTime() + _minEnd; } function votingMaxEndTime() public view returns (uint256) { return votingStartTime() + _maxEnd; } function name() public view returns (string memory) { return _name; } function description() public view returns (string memory) { return _description; } function execute_delegatecall(address, uint256) external { require(false, "not delegatecall-executable"); } function execute_call(uint256) external { require(false, "not call-executable"); } }
pragma solidity ^0.5.0; import "../../ownership/Ownable.sol"; import "../../governance/Governance.sol"; contract Cancelable is Ownable { constructor() public { Ownable.initialize(msg.sender); } function cancel(uint256 myID, address govAddress) external onlyOwner { Governance gov = Governance(govAddress); gov.cancelProposal(myID); } }
pragma solidity ^0.5.0; import "./BaseProposal.sol"; import "../../governance/Proposal.sol"; contract DelegatecallExecutableProposal is BaseProposal { // Returns execution type function executable() public view returns (Proposal.ExecType) { return Proposal.ExecType.DELEGATECALL; } function pType() public view returns (uint256) { return uint256(StdProposalTypes.UNKNOWN_DELEGATECALL_EXECUTABLE); } function execute_delegatecall(address, uint256) external { require(false, "must be overridden"); } }
pragma solidity ^0.5.0; import "../../governance/Proposal.sol"; /** * @dev An abstract proposal */ contract IProposal { // Get type of proposal (e.g. plaintext, software upgrade) function pType() external view returns (uint256); // Proposal execution type when proposal gets resolved function executable() external view returns (Proposal.ExecType); // Get min. turnout (ratio) function minVotes() external view returns (uint256); // Get min. agreement for options (ratio) function minAgreement() external view returns (uint256); // Get scales for opinions function opinionScales() external view returns (uint256[] memory); // Get options to choose from function options() external view returns (bytes32[] memory); // Get date when the voting starts function votingStartTime() external view returns (uint256); // Get date of earliest possible voting end function votingMinEndTime() external view returns (uint256); // Get date of latest possible voting end function votingMaxEndTime() external view returns (uint256); // execute proposal logic on approval (if executable == call) // Called via call opcode from governance contract function execute_call(uint256 optionID) external; // execute proposal logic on approval (if executable == delegatecall) // Called via delegatecall opcode from governance contract, hence selfAddress is provided function execute_delegatecall(address selfAddress, uint256 optionID) external; // Get human-readable name function name() external view returns (string memory); // Get human-readable description function description() external view returns (string memory); // Standard proposal types. The standard may be outdated, actual proposal templates may differ enum StdProposalTypes { NOT_INIT, UNKNOWN_NON_EXECUTABLE, UNKNOWN_CALL_EXECUTABLE, UNKNOWN_DELEGATECALL_EXECUTABLE } }
pragma solidity ^0.5.0; import "./base/Cancelable.sol"; import "./base/DelegatecallExecutableProposal.sol"; interface ConstsI { function updateMinSelfStake(uint256 v) external; function updateMaxDelegatedRatio(uint256 v) external; function updateValidatorCommission(uint256 v) external; function updateBurntFeeShare(uint256 v) external; // 4 function updateTreasuryFeeShare(uint256 v) external; function updateUnlockedRewardRatio(uint256 v) external; function updateMinLockupDuration(uint256 v) external; function updateMaxLockupDuration(uint256 v) external; // 8 function updateWithdrawalPeriodEpochs(uint256 v) external; function updateWithdrawalPeriodTime(uint256 v) external; function updateBaseRewardPerSecond(uint256 v) external; function updateOfflinePenaltyThresholdTime(uint256 v) external; // 12 function updateOfflinePenaltyThresholdBlocksNum(uint256 v) external; function updateTargetGasPowerPerSecond(uint256 v) external; function updateGasPriceBalancingCounterweight(uint256 v) external; // 15 } /** * @dev NetworkParameterProposal proposal */ contract NetworkParameterProposal is DelegatecallExecutableProposal, Cancelable { using SafeMath for uint256; Proposal.ExecType _exec; ConstsI public consts; uint8 public methodID; uint256[] public getOptionVal; constructor( string memory __description, uint8 __methodID, uint256[] memory __optionsVals, address __consts, uint256 __minVotes, uint256 __minAgreement, uint256 __start, uint256 __minEnd, uint256 __maxEnd, address verifier ) public { require(__methodID >= 1 && __methodID <= 15, "wrong methodID"); if (__methodID == 1) { _name = "Update minimum self-stake"; _options = uintsToStrs(__optionsVals, 1e18, " FTM"); } else if (__methodID == 2) { _name = "Update maximum delegated stake ratio"; _options = uintsToStrs(__optionsVals, 1e16, " %"); } else if (__methodID == 3) { _name = "Update validator rewards commission"; _options = uintsToStrs(__optionsVals, 1e16, " %"); } else if (__methodID == 4) { _name = "Update burnt fee share"; _options = uintsToStrs(__optionsVals, 1e16, " %"); } else if (__methodID == 5) { _name = "Update treasury fee share"; _options = uintsToStrs(__optionsVals, 1e16, " %"); } else if (__methodID == 6) { _name = "Update unlocked reward ratio"; _options = uintsToStrs(__optionsVals, 1e16, " %"); } else if (__methodID == 7) { _name = "Update minimum lockup duration"; _options = uintsToStrs(__optionsVals, 1440 minutes, " days"); } else if (__methodID == 8) { _name = "Update maximum lockup duration"; _options = uintsToStrs(__optionsVals, 1440 minutes, " days"); } else if (__methodID == 9) { _name = "Update number epochs of withdrawal period"; _options = uintsToStrs(__optionsVals, 1, ""); } else if (__methodID == 10) { _name = "Update withdrawal period"; _options = uintsToStrs(__optionsVals, 60 minutes, " hours"); } else if (__methodID == 11) { _name = "Update base reward per second"; _options = uintsToStrs(__optionsVals, 1e18, " FTM"); } else if (__methodID == 12) { _name = "Update time threshold for offline penalty"; _options = uintsToStrs(__optionsVals, 60 minutes, " hours"); } else if (__methodID == 13) { _name = "Update blocks threshold for offline penalty"; _options = uintsToStrs(__optionsVals, 1, ""); } else if (__methodID == 14) { _name = "Update target gas power second"; _options = uintsToStrs(__optionsVals, 1e6, " M"); } else { _name = "Update gas price balancing period"; _options = uintsToStrs(__optionsVals, 1 minutes, " minutes"); } _description = __description; methodID = __methodID; _minVotes = __minVotes; _minAgreement = __minAgreement; _start = __start; _minEnd = __minEnd; _maxEnd = __maxEnd; getOptionVal = __optionsVals; _opinionScales = [0, 1, 2, 3, 4]; consts = ConstsI(__consts); // verify the proposal right away to avoid deploying a wrong proposal if (verifier != address(0)) { require(verifyProposalParams(verifier), "failed verification"); } } function pType() public view returns (uint256) { // return 6003; return 4; } function optionVals() external view returns (uint256[] memory) { return getOptionVal; } event NetworkParameterUpgradeIsDone(uint256 newValue); function execute_delegatecall(address selfAddr, uint256 winnerOptionID) external { NetworkParameterProposal self = NetworkParameterProposal(selfAddr); uint256 __methodID = self.methodID(); if (__methodID == 1) { self.consts().updateMinSelfStake(self.getOptionVal(winnerOptionID)); } else if (__methodID == 2) { self.consts().updateMaxDelegatedRatio(self.getOptionVal(winnerOptionID)); } else if (__methodID == 3) { self.consts().updateValidatorCommission(self.getOptionVal(winnerOptionID)); } else if (__methodID == 4) { self.consts().updateBurntFeeShare(self.getOptionVal(winnerOptionID)); } else if (__methodID == 5) { self.consts().updateTreasuryFeeShare(self.getOptionVal(winnerOptionID)); } else if (__methodID == 6) { self.consts().updateUnlockedRewardRatio(self.getOptionVal(winnerOptionID)); } else if (__methodID == 7) { self.consts().updateMinLockupDuration(self.getOptionVal(winnerOptionID)); } else if (__methodID == 8) { self.consts().updateMaxLockupDuration(self.getOptionVal(winnerOptionID)); } else if (__methodID == 9) { self.consts().updateWithdrawalPeriodEpochs(self.getOptionVal(winnerOptionID)); } else if (__methodID == 10) { self.consts().updateWithdrawalPeriodTime(self.getOptionVal(winnerOptionID)); } else if (__methodID == 11) { self.consts().updateBaseRewardPerSecond(self.getOptionVal(winnerOptionID)); } else if (__methodID == 12) { self.consts().updateOfflinePenaltyThresholdTime(self.getOptionVal(winnerOptionID)); } else if (__methodID == 13) { self.consts().updateOfflinePenaltyThresholdBlocksNum(self.getOptionVal(winnerOptionID)); } else if (__methodID == 14) { self.consts().updateTargetGasPowerPerSecond(self.getOptionVal(winnerOptionID)); } else { self.consts().updateGasPriceBalancingCounterweight(self.getOptionVal(winnerOptionID)); } emit NetworkParameterUpgradeIsDone(self.getOptionVal(winnerOptionID)); } function decimalsNum(uint256 num) internal pure returns (uint256) { uint decimals; while (num != 0) { decimals++; num /= 10; } return decimals; } function uint256ToB(uint256 num) internal pure returns (bytes memory) { if (num == 0) { return bytes("0"); } uint decimals = decimalsNum(num); bytes memory bstr = new bytes(decimals); uint strIdx = decimals - 1; while (num != 0) { bstr[strIdx] = byte(uint8(48 + num % 10)); num /= 10; strIdx--; } return bstr; } function uint256ToStr(uint256 num) internal pure returns (string memory) { return string(uint256ToB(num)); } function decimalToStr(uint256 interger, uint256 fractional) internal pure returns (string memory) { bytes memory intStr = uint256ToB(interger); bytes memory fraStr = uint256ToB(fractional); // replace leading 1 with . fraStr[0] = byte(uint8(46)); return string(abi.encodePacked(intStr, fraStr)); } function unpackDecimal(uint256 num, uint256 unit) internal pure returns (uint256 interger, uint256 fractional) { assert(unit <= 1e18); fractional = (num % unit).mul(1e18).div(unit); return (num / unit, trimFractional(1e18 + fractional)); } function trimFractional(uint256 fractional) internal pure returns (uint256) { if (fractional == 0) { return 0; } while (fractional % 10 == 0) { fractional /= 10; } return fractional; } function uintsToStrs(uint256[] memory vals, uint256 unit, string memory symbol) internal pure returns (bytes32[] memory) { bytes32[] memory res = new bytes32[](vals.length); for (uint256 i = 0; i < vals.length; i++) { (uint256 interger, uint256 fractional) = unpackDecimal(vals[i], unit); if (fractional == 1) { res[i] = strToB32(string(abi.encodePacked(uint256ToStr(interger), symbol))); } else { res[i] = strToB32(string(abi.encodePacked(decimalToStr(interger, fractional), symbol))); } } return res; } function strToB32(string memory str) internal pure returns (bytes32 result) { bytes memory tempEmptyStringTest = bytes(str); require(tempEmptyStringTest.length <= 32, "string is too long"); if (tempEmptyStringTest.length == 0) { return 0x0; } assembly { result := mload(add(tempEmptyStringTest, 32)) } } }
pragma solidity ^0.5.0; import "./base/Cancelable.sol"; import "./base/DelegatecallExecutableProposal.sol"; /** * @dev An interface to update this contract to a destination address */ interface Upgradability { function upgradeTo(address newImplementation) external; } /** * @dev SoftwareUpgrade proposal */ contract SoftwareUpgradeProposal is DelegatecallExecutableProposal, Cancelable { address public upgradeableContract; address public newImplementation; constructor(string memory __name, string memory __description, uint256 __minVotes, uint256 __minAgreement, uint256 __start, uint256 __minEnd, uint256 __maxEnd, address __upgradeableContract, address __newImplementation, address verifier) public { _name = __name; _description = __description; _options.push(bytes32("Level of agreement")); _minVotes = __minVotes; _minAgreement = __minAgreement; _opinionScales = [0, 1, 2, 3, 4]; _start = __start; _minEnd = __minEnd; _maxEnd = __maxEnd; upgradeableContract = __upgradeableContract; newImplementation = __newImplementation; // verify the proposal right away to avoid deploying a wrong proposal if (verifier != address(0)) { require(verifyProposalParams(verifier), "failed verification"); } } function execute_delegatecall(address selfAddr, uint256) external { SoftwareUpgradeProposal self = SoftwareUpgradeProposal(selfAddr); Upgradability(self.upgradeableContract()).upgradeTo(self.newImplementation()); } }
pragma solidity ^0.5.0; import "../governance/Proposal.sol"; /** * @dev A verifier can verify a proposal's inputs such as proposal parameters and proposal contract. */ interface IProposalVerifier { // Verifies proposal parameters with respect to the stored template of same type function verifyProposalParams(uint256 pType, Proposal.ExecType executable, uint256 minVotes, uint256 minAgreement, uint256[] calldata opinionScales, uint256 start, uint256 minEnd, uint256 maxEnd) external view returns (bool); // Verifies proposal contract of the specified type and address function verifyProposalContract(uint256 pType, address propAddr) external view returns (bool); }
pragma solidity ^0.5.0; import "./IProposalVerifier.sol"; import "../governance/Governance.sol"; contract ScopedVerifier is IProposalVerifier { address internal unlockedFor; // verifyProposalParams checks proposal parameters function verifyProposalParams(uint256, Proposal.ExecType, uint256, uint256, uint256[] calldata, uint256, uint256, uint256) external view returns (bool) { return true; } // verifyProposalContract verifies proposal creator function verifyProposalContract(uint256, address propAddr) external view returns (bool) { return propAddr == unlockedFor; } }
pragma solidity ^0.5.0; /** * @dev The version info of this contract */ contract Version { /** * @dev Returns the version of this contract. */ function version() public pure returns (bytes4) { // version 00.0.2 return "0002"; } }
pragma solidity ^0.5.0; import "../ownership/Ownable.sol"; interface GovernanceI { function recountVote(address voterAddr, address delegatedTo, uint256 proposalID) external; function proposalState(uint256 proposalID) external view returns (uint256 winnerOptionID, uint256 votes, uint256 status); } contract VotesBookKeeper is Initializable, Ownable { address gov; uint256 public maxProposalsPerVoter; // voter, delegatedTo -> []proposal IDs mapping(address => mapping(address => uint256[])) votesList; // voter, delegatedTo, proposal ID -> {index in the list + 1} mapping(address => mapping(address => mapping(uint256 => uint256))) votesIndex; function initialize(address _owner, address _gov, uint256 _maxProposalsPerVoter) public initializer { Ownable.initialize(_owner); gov = _gov; maxProposalsPerVoter = _maxProposalsPerVoter; } function getProposalIDs(address voter, address delegatedTo) public view returns (uint256[] memory) { return votesList[voter][delegatedTo]; } // returns vote index plus 1 if vote exists. Returns 0 if vote doesn't exist function getVoteIndex(address voter, address delegatedTo, uint256 proposalID) public view returns (uint256) { return votesIndex[voter][delegatedTo][proposalID]; } function recountVotes(address voter, address delegatedTo) public { uint256[] storage list = votesList[voter][delegatedTo]; uint256 origLen = list.length; uint256 i = 0; for (uint256 iter = 0; iter < origLen; iter++) { (bool success,) = gov.call(abi.encodeWithSignature("recountVote(address,address,uint256)", voter, delegatedTo, list[i])); bool evicted = false; if (!success) { // unindex if proposal isn't active (,, uint256 status) = GovernanceI(gov).proposalState(list[i]); if (status != 0) { eraseVote(voter, delegatedTo, list[i], i + 1); evicted = true; } } if (!evicted) { i++; } } } function onVoted(address voter, address delegatedTo, uint256 proposalID) external { uint256 idx = votesIndex[voter][delegatedTo][proposalID]; if (idx > 0) { return; } if (votesList[voter][delegatedTo].length >= maxProposalsPerVoter) { // erase votes for outdated proposals recountVotes(voter, delegatedTo); } votesList[voter][delegatedTo].push(proposalID); idx = votesList[voter][delegatedTo].length; require(idx <= maxProposalsPerVoter, "too many votes"); votesIndex[voter][delegatedTo][proposalID] = idx; } function onVoteCanceled(address voter, address delegatedTo, uint256 proposalID) external { uint256 idx = votesIndex[voter][delegatedTo][proposalID]; if (idx == 0) { return; } eraseVote(voter, delegatedTo, proposalID, idx); } function eraseVote(address voter, address delegatedTo, uint256 proposalID, uint256 idx) internal { votesIndex[voter][delegatedTo][proposalID] = 0; uint256[] storage list = votesList[voter][delegatedTo]; uint256 len = list.length; if (len == idx) { // last element list.length--; } else { uint256 last = list[len - 1]; list[idx - 1] = last; list.length--; votesIndex[voter][delegatedTo][last] = idx; } } function setMaxProposalsPerVoter(uint256 v) onlyOwner external { maxProposalsPerVoter = v; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_governance","type":"address"},{"internalType":"address","name":"_constsAddress","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"constant":false,"inputs":[{"internalType":"string","name":"__description","type":"string"},{"internalType":"uint8","name":"__methodID","type":"uint8"},{"internalType":"uint256[]","name":"__optionVals","type":"uint256[]"},{"internalType":"uint256","name":"__minVotes","type":"uint256"},{"internalType":"uint256","name":"__minAgreement","type":"uint256"},{"internalType":"uint256","name":"__start","type":"uint256"},{"internalType":"uint256","name":"__minEnd","type":"uint256"},{"internalType":"uint256","name":"__maxEnd","type":"uint256"}],"name":"create","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"lastNetworkProposal","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"propAddr","type":"address"}],"name":"verifyProposalContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"enum Proposal.ExecType","name":"","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"verifyProposalParams","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5060405161362d38038061362d8339818101604052604081101561003357600080fd5b508051602090910151600180546001600160a01b039384166001600160a01b031991821617909155600280549390921692169190911790556135b38061007a6000396000f3fe608060405260043610620000445760003560e01c80632b6103bb146200004957806384d1113c146200007d578063d294ed2814620001d5578063f3f4ef791462000226575b600080fd5b3480156200005657600080fd5b5062000061620002d2565b604080516001600160a01b039092168252519081900360200190f35b620001d360048036036101008110156200009657600080fd5b810190602081018135640100000000811115620000b257600080fd5b820183602082011115620000c557600080fd5b80359060200191846001830284011164010000000083111715620000e857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929560ff8535169590949093506040810192506020013590506401000000008111156200014757600080fd5b8201836020820111156200015a57600080fd5b803590602001918460208302840111640100000000831117156200017d57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505082359350505060208101359060408101359060608101359060800135620002e1565b005b348015620001e257600080fd5b506200021260048036036040811015620001fb57600080fd5b50803590602001356001600160a01b03166200054b565b604080519115158252519081900360200190f35b3480156200023357600080fd5b506200021260048036036101008110156200024d57600080fd5b81359160ff6020820135169160408201359160608101359181019060a0810160808201356401000000008111156200028457600080fd5b8201836020820111156200029757600080fd5b80359060200191846020830284011164010000000083111715620002ba57600080fd5b91935091508035906020810135906040013562000561565b6003546001600160a01b031681565b6000888888600260009054906101000a90046001600160a01b031689898989896000604051620003119062000570565b80806020018b60ff1660ff168152602001806020018a6001600160a01b03166001600160a01b03168152602001898152602001888152602001878152602001868152602001858152602001846001600160a01b03166001600160a01b0316815260200183810383528d818151815260200191508051906020019080838360005b83811015620003ab57818101518382015260200162000391565b50505050905090810190601f168015620003d95780820380516001836020036101000a031916815260200191505b5083810382528b5181528b51602091820191808e01910280838360005b8381101562000410578181015183820152602001620003f6565b505050509050019c50505050505050505050505050604051809103906000f08015801562000442573d6000803e3d6000fd5b506040805163f2fde38b60e01b815233600482015290519192506001600160a01b0383169163f2fde38b9160248082019260009290919082900301818387803b1580156200048f57600080fd5b505af1158015620004a4573d6000803e3d6000fd5b5050600380546001600160a01b038086166001600160a01b031992831681179093556000805490921683178255600154604080516307eecaf560e01b8152600481019590955251911694506307eecaf593503492602480820193929182900301818588803b1580156200051657600080fd5b505af11580156200052b573d6000803e3d6000fd5b5050600080546001600160a01b0319169055505050505050505050505050565b6000546001600160a01b03908116911614919050565b60019998505050505050505050565b613000806200057f8339019056fe60806040523480156200001157600080fd5b50604051620030003803806200300083398181016040526101408110156200003857600080fd5b81019080805160405193929190846401000000008211156200005957600080fd5b9083019060208201858111156200006f57600080fd5b82516401000000008111828201881017156200008a57600080fd5b82525081516020918201929091019080838360005b83811015620000b95781810151838201526020016200009f565b50505050905090810190601f168015620000e75780820380516001836020036101000a031916815260200191505b506040818152602083015192018051929491939192846401000000008211156200011057600080fd5b9083019060208201858111156200012657600080fd5b82518660208202830111640100000000821117156200014457600080fd5b82525081516020918201928201910280838360005b838110156200017357818101518382015260200162000159565b50505050919091016040908152602083810151918401516060850151608086015160a087015160c088015160e090980151959950929750909590945090929091620001c9903390620017db62000943821b17901c565b60018960ff1610158015620001e25750600f8960ff1611155b62000225576040805162461bcd60e51b815260206004820152600e60248201526d1ddc9bdb99c81b595d1a1bd9125160921b604482015290519081900360640190fd5b8860ff1660011415620002cd576040805180820190915260198082527f557064617465206d696e696d756d2073656c662d7374616b650000000000000060209092019182526200027891600091620012db565b50620002b088670de0b6b3a7640000604051806040016040528060048152602001632046544d60e01b81525062000a4660201b60201c565b8051620002c6916002916020909101906200135c565b5062000805565b8860ff16600214156200033f5760405180606001604052806024815260200162002fbb6024913980516200030a91600091602090910190620012db565b50620002b088662386f26fc1000060405180604001604052806002815260200161202560f01b81525062000a4660201b60201c565b8860ff16600314156200037c5760405180606001604052806023815260200162002f6a6023913980516200030a91600091602090910190620012db565b8860ff1660041415620003cf576040805180820190915260168082527f557064617465206275726e74206665652073686172650000000000000000000060209092019182526200030a91600091620012db565b8860ff166005141562000422576040805180820190915260198082527f557064617465207472656173757279206665652073686172650000000000000060209092019182526200030a91600091620012db565b8860ff1660061415620004755760408051808201909152601c8082527f55706461746520756e6c6f636b65642072657761726420726174696f0000000060209092019182526200030a91600091620012db565b8860ff1660071415620004fc5760408051808201909152601e8082527f557064617465206d696e696d756d206c6f636b7570206475726174696f6e00006020909201918252620004c891600091620012db565b50620002b0886201518060405180604001604052806005815260200164206461797360d81b81525062000a4660201b60201c565b8860ff16600814156200054f5760408051808201909152601e8082527f557064617465206d6178696d756d206c6f636b7570206475726174696f6e00006020909201918252620004c891600091620012db565b8860ff1660091415620005b05760405180606001604052806029815260200162002ef76029913980516200058c91600091602090910190620012db565b50620002b08860016040518060200160405280600081525062000a4660201b60201c565b8860ff16600a141562000637576040805180820190915260188082527f557064617465207769746864726177616c20706572696f64000000000000000060209092019182526200060391600091620012db565b50620002b088610e106040518060400160405280600681526020016520686f75727360d01b81525062000a4660201b60201c565b8860ff16600b14156200068a5760408051808201909152601d8082527f55706461746520626173652072657761726420706572207365636f6e6400000060209092019182526200027891600091620012db565b8860ff16600c1415620006c75760405180606001604052806029815260200162002f206029913980516200060391600091602090910190620012db565b8860ff16600d141562000704576040518060600160405280602b815260200162002ecc602b913980516200058c91600091602090910190620012db565b8860ff16600e1415620007885760408051808201909152601e8082527f557064617465207461726765742067617320706f776572207365636f6e64000060209092019182526200075791600091620012db565b50620002b088620f424060405180604001604052806002815260200161204d60f01b81525062000a4660201b60201c565b60405180606001604052806021815260200162002fdf602191398051620007b891600091602090910190620012db565b50620007ed88603c60405180604001604052806008815260200167206d696e7574657360c01b81525062000a4660201b60201c565b805162000803916002916020909101906200135c565b505b89516200081a9060019060208d0190620012db565b50606f805460ff60a81b1916600160a81b60ff8c1602179055600386905560048590556006849055600783905560088290558751620008619060709060208b01906200135c565b506040805160a081018252600081526001602082015260029181019190915260036060820152600460808201526200089d906005908162001399565b50606f80546001600160a01b03808a1661010002610100600160a81b0319909216919091179091558116156200093357620008e1816001600160e01b0362000bfa16565b62000933576040805162461bcd60e51b815260206004820152601360248201527f6661696c656420766572696669636174696f6e00000000000000000000000000604482015290519081900360640190fd5b50505050505050505050620013f9565b600954610100900460ff1680620009685750620009686001600160e01b0362000d9016565b8062000977575060095460ff16155b620009b45760405162461bcd60e51b815260040180806020018281038252602e81526020018062002f8d602e913960400191505060405180910390fd5b600954610100900460ff16158015620009e0576009805460ff1961ff0019909116610100171660011790555b603c80546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3801562000a42576009805461ff00191690555b5050565b606080845160405190808252806020026020018201604052801562000a75578160200160208202803883390190505b50905060005b855181101562000bf15760008062000aae88848151811062000a9957fe5b60200260200101518862000d9760201b60201c565b91509150806001141562000bb35762000b9462000ad4836001600160e01b0362000e2816565b876040516020018083805190602001908083835b6020831062000b095780518252601f19909201916020918201910162000ae8565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831062000b535780518252601f19909201916020918201910162000b32565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405262000e4460201b60201c565b84848151811062000ba157fe5b60200260200101818152505062000be6565b62000bcc62000ad483836001600160e01b0362000eb416565b84848151811062000bd957fe5b6020026020010181815250505b505060010162000a7b565b50949350505050565b6000816001600160a01b03811663f3f4ef7962000c1f6001600160e01b0362000fce16565b62000c326001600160e01b0362000fd316565b62000c456001600160e01b0362000fd816565b62000c586001600160e01b0362000fde16565b62000c6b6001600160e01b0362000fe416565b62000c7e6001600160e01b036200103e16565b62000c916001600160e01b036200104616565b62000ca46001600160e01b036200106516565b6040518963ffffffff1660e01b81526004018089815260200188600281111562000cca57fe5b60ff16815260200187815260200186815260200180602001858152602001848152602001838152602001828103825286818151815260200191508051906020019060200280838360005b8381101562000d2e57818101518382015260200162000d14565b50505050905001995050505050505050505060206040518083038186803b15801562000d5957600080fd5b505afa15801562000d6e573d6000803e3d6000fd5b505050506040513d602081101562000d8557600080fd5b50519150505b919050565b303b155b90565b600080670de0b6b3a764000083111562000dad57fe5b62000df28362000dde670de0b6b3a764000086888162000dc957fe5b066200107e60201b620018cd1790919060201c565b620010e360201b6200192f1790919060201c565b905082848162000dfe57fe5b0462000e1d670de0b6b3a764000083016001600160e01b036200112d16565b915091509250929050565b606062000e3e826001600160e01b036200115716565b92915050565b6000606082905060208151111562000e98576040805162461bcd60e51b8152602060048201526012602482015271737472696e6720697320746f6f206c6f6e6760701b604482015290519081900360640190fd5b805162000eaa57506000905062000d8b565b6020015192915050565b60608062000ecb846001600160e01b036200115716565b9050606062000ee3846001600160e01b036200115716565b9050602e60f81b8160008151811062000ef857fe5b60200101906001600160f81b031916908160001a90535081816040516020018083805190602001908083835b6020831062000f455780518252601f19909201916020918201910162000f24565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831062000f8f5780518252601f19909201916020918201910162000f6e565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040529250505092915050565b600490565b600290565b60035490565b60045490565b606060058054806020026020016040519081016040528092919081815260200182805480156200103457602002820191906000526020600020905b8154815260200190600101908083116200101f575b5050505050905090565b600654420190565b6007546000906200105f6001600160e01b036200103e16565b01905090565b6008546000906200105f6001600160e01b036200103e16565b6000826200108f5750600062000e3e565b828202828482816200109d57fe5b0414620010dc5760405162461bcd60e51b815260040180806020018281038252602181526020018062002f496021913960400191505060405180910390fd5b9392505050565b6000620010dc83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506200121a60201b60201c565b6000816200113e5750600062000d8b565b600a82066200115357600a820491506200113e565b5090565b6060816200117e57506040805180820190915260018152600360fc1b602082015262000d8b565b600062001194836001600160e01b03620012c116565b90506060816040519080825280601f01601f191660200182016040528015620011c4576020820181803883390190505b50905060001982015b84156200121257600a850660300160f81b828281518110620011eb57fe5b60200101906001600160f81b031916908160001a905350600a8504945060001901620011cd565b509392505050565b60008183620012aa5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156200126e57818101518382015260200162001254565b50505050905090810190601f1680156200129c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581620012b757fe5b0495945050505050565b6000805b821562000e3e57600101600a83049250620012c5565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200131e57805160ff19168380011785556200134e565b828001600101855582156200134e579182015b828111156200134e57825182559160200191906001019062001331565b5062001153929150620013dc565b8280548282559060005260206000209081019282156200134e57916020028201828111156200134e57825182559160200191906001019062001331565b8280548282559060005260206000209081019282156200134e579160200282015b828111156200134e578251829060ff16905591602001919060010190620013ba565b62000d9491905b80821115620011535760008155600101620013e3565b611ac380620014096000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c8063715018a6116100c3578063a61e393a1161007c578063a61e393a14610355578063aa3daba91461035d578063cb00e7d314610389578063d86d744e146103af578063e6f94d55146103b7578063f2fde38b146103d55761014d565b8063715018a6146102e05780637284e416146102e857806389d5b8ea146102f05780638da5cb5b1461030d5780638f32d59b146103315780639b3a8a071461034d5761014d565b80632842f0c2116101155780632842f0c2146102755780633cc228fd1461027d57806357d682c41461028557806363012d01146102b35780636eb067a0146102d05780636f24f8a1146102d85761014d565b806306fdde03146101525780631069143a146101cf57806316131a18146102275780632019a60814610253578063216b91161461026d575b600080fd5b61015a6103fb565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561019457818101518382015260200161017c565b50505050905090810190601f1680156101c15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101d7610491565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102135781810151838201526020016101fb565b505050509050019250505060405180910390f35b61022f6104e8565b6040518082600281111561023f57fe5b60ff16815260200191505060405180910390f35b61025b6104ed565b60408051918252519081900360200190f35b61025b6104f5565b6101d76104fa565b61025b610550565b6102b16004803603604081101561029b57600080fd5b50803590602001356001600160a01b0316610556565b005b6102b1600480360360208110156102c957600080fd5b5035610617565b61025b61065d565b6101d7610663565b6102b16106b9565b61015a61075c565b61025b6004803603602081101561030657600080fd5b50356107bc565b6103156107da565b604080516001600160a01b039092168252519081900360200190f35b6103396107e9565b604080519115158252519081900360200190f35b61025b6107fa565b61025b61080d565b6102b16004803603604081101561037357600080fd5b506001600160a01b03813516906020013561081a565b6103396004803603602081101561039f57600080fd5b50356001600160a01b0316611583565b6103156116b9565b6103bf6116cd565b6040805160ff9092168252519081900360200190f35b6102b1600480360360208110156103eb57600080fd5b50356001600160a01b03166116dd565b60008054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104875780601f1061045c57610100808354040283529160200191610487565b820191906000526020600020905b81548152906001019060200180831161046a57829003601f168201915b5050505050905090565b6060600280548060200260200160405190810160405280929190818152602001828054801561048757602002820191906000526020600020905b8154815260200190600101908083116104cb575050505050905090565b600290565b600654420190565b600490565b6060607080548060200260200160405190810160405280929190818152602001828054801561048757602002820191906000526020600020908154815260200190600101908083116104cb575050505050905090565b60035490565b61055e6107e9565b6105af576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000819050806001600160a01b031663e0a8f6f5846040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156105fa57600080fd5b505af115801561060e573d6000803e3d6000fd5b50505050505050565b6040805162461bcd60e51b81526020600482015260136024820152726e6f742063616c6c2d65786563757461626c6560681b604482015290519081900360640190fd5b50565b60045490565b6060600580548060200260200160405190810160405280929190818152602001828054801561048757602002820191906000526020600020908154815260200190600101908083116104cb575050505050905090565b6106c16107e9565b610712576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b603c546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603c80546001600160a01b0319169055565b60018054604080516020601f600260001961010087891615020190951694909404938401819004810282018101909252828152606093909290918301828280156104875780601f1061045c57610100808354040283529160200191610487565b607081815481106107c957fe5b600091825260209091200154905081565b603c546001600160a01b031690565b603c546001600160a01b0316331490565b60006007546108076104ed565b01905090565b60006008546108076104ed565b60008290506000816001600160a01b031663e6f94d556040518163ffffffff1660e01b815260040160206040518083038186803b15801561085a57600080fd5b505afa15801561086e573d6000803e3d6000fd5b505050506040513d602081101561088457600080fd5b505160ff16905060018114156109d357816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156108cd57600080fd5b505afa1580156108e1573d6000803e3d6000fd5b505050506040513d60208110156108f757600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b039283169263866c4b1792908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b505afa158015610960573d6000803e3d6000fd5b505050506040513d602081101561097657600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b1580156109b657600080fd5b505af11580156109ca573d6000803e3d6000fd5b505050506114db565b8060021415610a9457816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610a1557600080fd5b505afa158015610a29573d6000803e3d6000fd5b505050506040513d6020811015610a3f57600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b03928316926381ffcdf192908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b8060031415610b5557816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ad657600080fd5b505afa158015610aea573d6000803e3d6000fd5b505050506040513d6020811015610b0057600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b0392831692632ee7113292908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b8060041415610c1657816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b9757600080fd5b505afa158015610bab573d6000803e3d6000fd5b505050506040513d6020811015610bc157600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b0392831692632bb9fe8d92908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b8060051415610cd757816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c5857600080fd5b505afa158015610c6c573d6000803e3d6000fd5b505050506040513d6020811015610c8257600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b039283169263f8d5177e92908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b8060061415610d9857816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d1957600080fd5b505afa158015610d2d573d6000803e3d6000fd5b505050506040513d6020811015610d4357600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b0392831692637945ef9992908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b8060071415610e5957816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610dda57600080fd5b505afa158015610dee573d6000803e3d6000fd5b505050506040513d6020811015610e0457600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b039283169263bf25338b92908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b8060081415610f1a57816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e9b57600080fd5b505afa158015610eaf573d6000803e3d6000fd5b505050506040513d6020811015610ec557600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b039283169263ad7b3f7b92908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b8060091415610fdb57816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f5c57600080fd5b505afa158015610f70573d6000803e3d6000fd5b505050506040513d6020811015610f8657600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b0392831692638f078bfa92908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b80600a141561109c57816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561101d57600080fd5b505afa158015611031573d6000803e3d6000fd5b505050506040513d602081101561104757600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b039283169263455366a492908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b80600b141561115d57816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110de57600080fd5b505afa1580156110f2573d6000803e3d6000fd5b505050506040513d602081101561110857600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b039283169263b6d9edd592908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b80600c141561121e57816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561119f57600080fd5b505afa1580156111b3573d6000803e3d6000fd5b505050506040513d60208110156111c957600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b0392831692636348ebb892908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b80600d14156112df57816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561126057600080fd5b505afa158015611274573d6000803e3d6000fd5b505050506040513d602081101561128a57600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b0392831692632e84e8e692908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b80600e14156113a057816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561132157600080fd5b505afa158015611335573d6000803e3d6000fd5b505050506040513d602081101561134b57600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b0392831692634332686792908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113d957600080fd5b505afa1580156113ed573d6000803e3d6000fd5b505050506040513d602081101561140357600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b039283169263d3f48dbe92908616916389d5b8ea91602480820192602092909190829003018186803b15801561145857600080fd5b505afa15801561146c573d6000803e3d6000fd5b505050506040513d602081101561148257600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b1580156114c257600080fd5b505af11580156114d6573d6000803e3d6000fd5b505050505b7f429f0e2ca73311a31e395b735e0bff6a88fb01c4f53b8dcdde0a6f208ee2f6ce826001600160a01b03166389d5b8ea856040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561154057600080fd5b505afa158015611554573d6000803e3d6000fd5b505050506040513d602081101561156a57600080fd5b505160408051918252519081900360200190a150505050565b6000816001600160a01b03811663f3f4ef7961159d6104f5565b6115a56104e8565b6115ad610550565b6115b561065d565b6115bd610663565b6115c56104ed565b6115cd6107fa565b6115d561080d565b6040518963ffffffff1660e01b8152600401808981526020018860028111156115fa57fe5b60ff16815260200187815260200186815260200180602001858152602001848152602001838152602001828103825286818151815260200191508051906020019060200280838360005b8381101561165c578181015183820152602001611644565b50505050905001995050505050505050505060206040518083038186803b15801561168657600080fd5b505afa15801561169a573d6000803e3d6000fd5b505050506040513d60208110156116b057600080fd5b50519392505050565b606f5461010090046001600160a01b031681565b606f54600160a81b900460ff1681565b6116e56107e9565b611736576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b61065a816001600160a01b03811661177f5760405162461bcd60e51b8152600401808060200182810382526026815260200180611a1a6026913960400191505060405180910390fd5b603c546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603c80546001600160a01b0319166001600160a01b0392909216919091179055565b600954610100900460ff16806117f457506117f4611971565b80611802575060095460ff16155b61183d5760405162461bcd60e51b815260040180806020018281038252602e815260200180611a61602e913960400191505060405180910390fd5b600954610100900460ff16158015611868576009805460ff1961ff0019909116610100171660011790555b603c80546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a380156118c9576009805461ff00191690555b5050565b6000826118dc57506000611929565b828202828482816118e957fe5b04146119265760405162461bcd60e51b8152600401808060200182810382526021815260200180611a406021913960400191505060405180910390fd5b90505b92915050565b600061192683836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611977565b303b1590565b60008183611a035760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156119c85781810151838201526020016119b0565b50505050905090810190601f1680156119f55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581611a0f57fe5b049594505050505056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a72315820d9717271113959374c09d444a1ba5eafcc9e63b058830c9d7dc03b72e8c0b14b64736f6c6343000511003255706461746520626c6f636b73207468726573686f6c6420666f72206f66666c696e652070656e616c7479557064617465206e756d6265722065706f636873206f66207769746864726177616c20706572696f645570646174652074696d65207468726573686f6c6420666f72206f66666c696e652070656e616c7479536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775570646174652076616c696461746f72207265776172647320636f6d6d697373696f6e436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564557064617465206d6178696d756d2064656c656761746564207374616b6520726174696f557064617465206761732070726963652062616c616e63696e6720706572696f64a265627a7a72315820e5a8126504e5adc65c22d0a64f04531f942f3b7928f32e565a6f49e44e7314d264736f6c63430005110032000000000000000000000000aa3a160e91f63f1db959640e0a7b8911b6bd5b95000000000000000000000000f58d44b8957ab7a6384c9a6079f7554311d52e9c
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Validator ID :
0 FTM
Amount Staked
0
Amount Delegated
0
Staking Total
0
Staking Start Epoch
0
Staking Start Time
0
Proof of Importance
0
Origination Score
0
Validation Score
0
Active
0
Online
0
Downtime
0 s
Address | Amount | claimed Rewards | Created On Epoch | Created On |
---|