mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 18:02:24 +00:00
updatp contract, return old code
This commit is contained in:
parent
bcfce2af3d
commit
0d7583ea31
4 changed files with 545 additions and 135 deletions
|
|
@ -6,14 +6,19 @@ import "./libs/SafeMath.sol";
|
|||
contract TomoValidator is IValidator {
|
||||
using SafeMath for uint256;
|
||||
|
||||
event Vote(address _candidate, uint256 _cap);
|
||||
event Unvote(address _candidate, uint256 _cap);
|
||||
event Propose(address _candidate, uint256 _cap);
|
||||
event Retire(address _candidate, uint256 _cap);
|
||||
event Vote(address _voter, address _candidate, uint256 _cap);
|
||||
event Unvote(address _voter, address _candidate, uint256 _cap);
|
||||
event Propose(address _backer, address _candidate, uint256 _cap);
|
||||
event Resign(address _backer, address _candidate);
|
||||
event SetNodeUrl(address _backer, address _candidate, string _nodeUrl);
|
||||
event Withdraw(address _backer, address _candidate, uint256 _cap);
|
||||
|
||||
struct ValidatorState {
|
||||
address backer;
|
||||
string nodeUrl;
|
||||
bool isCandidate;
|
||||
uint256 cap;
|
||||
uint256 withdrawBlockNumber;
|
||||
mapping(address => uint256) voters;
|
||||
}
|
||||
|
||||
|
|
@ -21,16 +26,55 @@ contract TomoValidator is IValidator {
|
|||
mapping(address => address[]) voters;
|
||||
address[] public candidates;
|
||||
uint256 candidateCount = 0;
|
||||
uint256 public constant minCandidateCap = 10000 ether;
|
||||
uint256 public constant maxCandidateNumber = 500;
|
||||
uint256 public constant minCandidateCap = 50000 ether;
|
||||
uint256 public constant maxValidatorNumber = 99;
|
||||
|
||||
modifier onlyValidCandidateCap {
|
||||
// anyone can deposit 10000 TOMO to become a candidate
|
||||
require(msg.value >= minCandidateCap);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier onlyBacker(address _candidate) {
|
||||
require(validatorsState[_candidate].backer == msg.sender);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier onlyCandidate(address _candidate) {
|
||||
require(validatorsState[_candidate].isCandidate);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier onlyAlreadyResigned(address _candidate) {
|
||||
require(validatorsState[_candidate].withdrawBlockNumber > 0);
|
||||
require(block.number >= validatorsState[_candidate].withdrawBlockNumber);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier onlyValidCandidate (address _candidate) {
|
||||
require(validatorsState[_candidate].isCandidate);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier onlyNotCandidate (address _candidate) {
|
||||
require(!validatorsState[_candidate].isCandidate);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier onlyValidVote (address _candidate, uint256 _cap) {
|
||||
require(validatorsState[_candidate].voters[msg.sender] >= _cap);
|
||||
_;
|
||||
}
|
||||
|
||||
function TomoValidator(address[] _candidates, uint256[] _caps) public {
|
||||
candidates = _candidates;
|
||||
|
||||
for (uint256 i = 0; i < _candidates.length; i++) {
|
||||
validatorsState[_candidates[i]] = ValidatorState({
|
||||
backer: msg.sender,
|
||||
nodeUrl: '',
|
||||
isCandidate: true,
|
||||
withdrawBlockNumber: 0,
|
||||
cap: _caps[i]
|
||||
});
|
||||
candidateCount = candidateCount + 1;
|
||||
|
|
@ -38,37 +82,49 @@ contract TomoValidator is IValidator {
|
|||
|
||||
}
|
||||
|
||||
function propose() external payable {
|
||||
// anyone can deposit 10000 TOMO to become a candidate
|
||||
require(msg.value >= minCandidateCap);
|
||||
require(!validatorsState[msg.sender].isCandidate);
|
||||
require(candidateCount <= maxCandidateNumber);
|
||||
candidates.push(msg.sender);
|
||||
validatorsState[msg.sender] = ValidatorState({
|
||||
function propose(address _candidate, string _nodeUrl) external payable onlyValidCandidateCap onlyNotCandidate(_candidate) {
|
||||
candidates.push(_candidate);
|
||||
validatorsState[_candidate] = ValidatorState({
|
||||
backer: msg.sender,
|
||||
nodeUrl: _nodeUrl,
|
||||
isCandidate: true,
|
||||
withdrawBlockNumber: 0,
|
||||
cap: msg.value
|
||||
});
|
||||
validatorsState[msg.sender].voters[msg.sender] = msg.value;
|
||||
validatorsState[_candidate].voters[msg.sender] = msg.value;
|
||||
candidateCount = candidateCount + 1;
|
||||
emit Propose(msg.sender, msg.value);
|
||||
emit Propose(msg.sender, _candidate, msg.value);
|
||||
}
|
||||
|
||||
function vote(address _candidate) external payable {
|
||||
require(validatorsState[_candidate].isCandidate);
|
||||
function vote(address _candidate) external payable onlyValidCandidate(_candidate) {
|
||||
validatorsState[_candidate].cap = validatorsState[_candidate].cap.add(msg.value);
|
||||
if (validatorsState[_candidate].voters[msg.sender] == 0) {
|
||||
voters[_candidate].push(msg.sender);
|
||||
}
|
||||
validatorsState[_candidate].voters[msg.sender] = validatorsState[_candidate].voters[msg.sender].add(msg.value);
|
||||
voters[_candidate].push(msg.sender);
|
||||
emit Vote(_candidate, msg.value);
|
||||
emit Vote(msg.sender, _candidate, msg.value);
|
||||
}
|
||||
|
||||
function getCandidates() public view returns(address[]) {
|
||||
return candidates;
|
||||
return candidates;
|
||||
}
|
||||
|
||||
function getCandidateCap(address _candidate) public view returns(uint256) {
|
||||
return validatorsState[_candidate].cap;
|
||||
}
|
||||
|
||||
function getCandidateNodeUrl(address _candidate) public view returns(string) {
|
||||
return validatorsState[_candidate].nodeUrl;
|
||||
}
|
||||
|
||||
function getCandidateBacker(address _candidate) public view returns(address) {
|
||||
return validatorsState[_candidate].backer;
|
||||
}
|
||||
|
||||
function getCandidateWithdrawBlockNumber(address _candidate) public view returns(uint256) {
|
||||
return validatorsState[_candidate].withdrawBlockNumber;
|
||||
}
|
||||
|
||||
function getVoterCap(address _candidate, address _voter) public view returns(uint256) {
|
||||
return validatorsState[_candidate].voters[_voter];
|
||||
}
|
||||
|
|
@ -78,34 +134,42 @@ contract TomoValidator is IValidator {
|
|||
}
|
||||
|
||||
function isCandidate(address _candidate) public view returns(bool) {
|
||||
return validatorsState[_candidate].isCandidate;
|
||||
return validatorsState[_candidate].isCandidate;
|
||||
}
|
||||
|
||||
function unvote(address _candidate, uint256 _cap) public {
|
||||
require(validatorsState[_candidate].voters[msg.sender] >= _cap);
|
||||
function unvote(address _candidate, uint256 _cap) public onlyValidVote(_candidate, _cap) {
|
||||
validatorsState[_candidate].cap = validatorsState[_candidate].cap.sub(_cap);
|
||||
validatorsState[_candidate].voters[msg.sender] = validatorsState[_candidate].voters[msg.sender].sub(_cap);
|
||||
// refunding to user after unvoting
|
||||
msg.sender.transfer(_cap);
|
||||
emit Unvote(_candidate, _cap);
|
||||
emit Unvote(msg.sender, _candidate, _cap);
|
||||
}
|
||||
|
||||
function retire() public {
|
||||
require(validatorsState[msg.sender].isCandidate);
|
||||
uint256 cap = validatorsState[msg.sender].voters[msg.sender];
|
||||
validatorsState[msg.sender].cap = validatorsState[msg.sender].cap.sub(cap);
|
||||
validatorsState[msg.sender].voters[msg.sender] = 0;
|
||||
validatorsState[msg.sender].isCandidate = false;
|
||||
function setNodeUrl(address _candidate, string _nodeUrl) public onlyBacker(_candidate) {
|
||||
validatorsState[_candidate].nodeUrl = _nodeUrl;
|
||||
emit SetNodeUrl(msg.sender, _candidate, _nodeUrl);
|
||||
}
|
||||
|
||||
function resign(address _candidate) public onlyBacker(_candidate) onlyCandidate(_candidate) {
|
||||
validatorsState[_candidate].isCandidate = false;
|
||||
candidateCount = candidateCount - 1;
|
||||
for (uint256 i = 0; i < candidates.length; i++) {
|
||||
if (candidates[i] == msg.sender) {
|
||||
if (candidates[i] == _candidate) {
|
||||
delete candidates[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// refunding to user after retiring
|
||||
msg.sender.transfer(cap);
|
||||
emit Retire(msg.sender, cap);
|
||||
// refunding after retiring 100 blocks
|
||||
validatorsState[_candidate].withdrawBlockNumber = validatorsState[_candidate].withdrawBlockNumber.add(block.number).add(100);
|
||||
emit Resign(msg.sender, _candidate);
|
||||
}
|
||||
|
||||
function withdraw(address _candidate) public onlyBacker(_candidate) onlyNotCandidate(_candidate) onlyAlreadyResigned(_candidate) {
|
||||
uint256 cap = validatorsState[_candidate].voters[msg.sender];
|
||||
validatorsState[_candidate].cap = validatorsState[_candidate].cap.sub(cap);
|
||||
validatorsState[_candidate].voters[msg.sender] = 0;
|
||||
validatorsState[_candidate].withdrawBlockNumber = 0;
|
||||
msg.sender.transfer(cap);
|
||||
emit Withdraw(msg.sender, _candidate, cap);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
pragma solidity ^0.4.21;
|
||||
|
||||
interface IValidator {
|
||||
function propose() external payable;
|
||||
function propose(address, string) external payable;
|
||||
function vote(address) external payable;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -30,10 +30,11 @@ func TestValidator(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("can't get candidates: %v", err)
|
||||
}
|
||||
t.Log("candidates", candidates)
|
||||
for _, it := range candidates {
|
||||
cap, _ := validator.GetCandidateCap(it)
|
||||
t.Log("candidate", it.String(), "cap", cap)
|
||||
backer, _ := validator.GetCandidateBacker(it)
|
||||
t.Log("candidate", it.String(), "backer", backer.String())
|
||||
}
|
||||
contractBackend.Commit()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue