-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
StdDaoToken vulnerability fix: startNewVoting() and finishVoting() ca… #209
Changes from all commits
0865fa9
a37d3c5
1e93bb7
2cd650b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,15 +9,15 @@ pragma solidity ^0.4.22; | |
contract IVoting { | ||
// _tokenAmount -> if this voting type DOES NOT use tokens -> set to any value (e.g., 0); | ||
// will execute action automatically if the voting is finished | ||
function vote(bool _yes, uint _tokenAmount) public; | ||
function vote(bool _yes, uint _tokenAmount, uint _votingID) public; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ты добавил ВО ВСЕ методы Voting'ов _votingID. Так быть не должно:
|
||
|
||
// stop the voting | ||
function cancelVoting() public; | ||
|
||
// This is for statistics | ||
// Can get this stats if voting is finished. | ||
// Can get this stats if voting is NOT finished. | ||
function getVotingStats() public view returns(uint yesResults, uint noResults, uint totalResults); | ||
function getVotingStats(uint _votingID) public view returns(uint yesResults, uint noResults, uint totalResults); | ||
|
||
// Is voting finished? | ||
// | ||
|
@@ -29,7 +29,7 @@ contract IVoting { | |
// When isFinished(): | ||
// 1 - i can not vote any more | ||
// 2 - i can get results with isYes() | ||
function isFinished()public view returns(bool); | ||
function isFinished(uint _votingID)public view returns(bool); | ||
|
||
// The result of voting | ||
// | ||
|
@@ -38,7 +38,7 @@ contract IVoting { | |
// 2 - all these conditions should be met: | ||
// 2.1 - isFinished() | ||
// 2.2 - is quorum reached | ||
function isYes()public view returns(bool); | ||
function isYes(uint _votingID)public view returns(bool); | ||
} | ||
|
||
/** | ||
|
@@ -52,16 +52,16 @@ contract IDelegationTable { | |
// @dev delegateMyVoiceTo() will override the currently set value. | ||
// I.e., if you called delegateMyVoiceTo(A,10) and then delegateMyVoiceTo(A,20) again, | ||
// then getDelegatedPowerByMe(A) is 20 (not 30!) | ||
function delegateMyVoiceTo(address _to, uint _tokenAmount) public; | ||
function delegateMyVoiceTo(address _to, uint _tokenAmount, uint _votingID) public; | ||
// @dev Returns how much i delegated power to _to | ||
function getDelegatedPowerByMe(address _to) public view returns(uint); | ||
function getDelegatedPowerByMe(address _to, uint _votingID) public view returns(uint); | ||
// @dev Cancel the delegation of power to _to | ||
function removeDelegation(address _to) public; | ||
function removeDelegation(address _to, uint _votingID) public; | ||
|
||
// @dev Returns the sum of: balance of _who AND the total delegated power of _who | ||
function getPowerOf(address _who) public view returns(uint); | ||
function getPowerOf(address _who, uint _votingID) public view returns(uint); | ||
// @dev Returns the total delegated power of _who | ||
function getDelegatedPowerOf(address _of) public view returns(uint); | ||
function getDelegatedPowerOf(address _of, uint _votingID) public view returns(uint); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,7 @@ contract LiquidVoting is IDelegationTable, Voting_SimpleToken { | |
event DelegatedTo(address _sender, uint _tokensAmount); | ||
event DelegationRemoved(address _from, address _to); | ||
|
||
mapping (address => Delegation[]) delegations; | ||
mapping (uint => mapping(address => Delegation[])) delegations; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Как понять логику "в одном контракте Voting может быть МНОЖЕСТВО привязанных индексов голосований токена"? Зачем тут uint => mapping появился? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ну типо, у одного инстанса Voting может быть 20 votings с разными ID |
||
|
||
constructor(IDaoBase _dao, IProposal _proposal, | ||
address _origin, uint _minutesToVote, | ||
|
@@ -27,94 +27,94 @@ contract LiquidVoting is IDelegationTable, Voting_SimpleToken { | |
{ | ||
} | ||
|
||
function internalVote(address _who, bool _yes) internal { | ||
uint tokenBalance = getPowerOf(_who); | ||
function internalVote(address _who, bool _yes, uint _votingID) internal { | ||
uint tokenBalance = getPowerOf(_who, _votingID); | ||
|
||
require(!addressVotedAlready[_who]); | ||
require(!addressVotedAlready[votingID][_who]); | ||
|
||
tokenVotesArray.push(TokenVote(_who, _yes, tokenBalance)); | ||
addressVotedAlready[_who] = true; | ||
tokenVotesArray[_votingID].push(TokenVote(_who, _yes, tokenBalance)); | ||
addressVotedAlready[votingID][_who] = true; | ||
|
||
emit VotingSimpleToken_Vote(_who, _yes, tokenBalance); | ||
|
||
callActionIfEnded(); | ||
callActionIfEnded(_votingID); | ||
} | ||
|
||
function getPowerOf(address _who) public view returns(uint){ | ||
uint res = stdDaoToken.getBalanceAtVoting(votingID, _who); | ||
function getPowerOf(address _who, uint _votingID) public view returns(uint){ | ||
uint res = stdDaoToken.getBalanceAtVoting(_votingID, _who); | ||
|
||
for(uint i = 0; i < delegations[_who].length; i++){ | ||
if(!delegations[_who][i].isDelegator){ | ||
res += delegations[_who][i].amount; | ||
for(uint i = 0; i < delegations[_votingID][_who].length; i++){ | ||
if(!delegations[_votingID][_who][i].isDelegator){ | ||
res += delegations[_votingID][_who][i].amount; | ||
} | ||
if(delegations[_who][i].isDelegator){ | ||
res -= delegations[_who][i].amount; | ||
if(delegations[_votingID][_who][i].isDelegator){ | ||
res -= delegations[_votingID][_who][i].amount; | ||
} | ||
} | ||
|
||
return res; | ||
} | ||
|
||
function getDelegatedPowerOf(address _of) public view returns(uint) { | ||
function getDelegatedPowerOf(address _of, uint _votingID) public view returns(uint) { | ||
uint res; | ||
|
||
for(uint i = 0; i < delegations[_of].length; i++){ | ||
if(!delegations[_of][i].isDelegator){ | ||
res += delegations[_of][i].amount; | ||
for(uint i = 0; i < delegations[_votingID][_of].length; i++){ | ||
if(!delegations[_votingID][_of][i].isDelegator){ | ||
res += delegations[_votingID][_of][i].amount; | ||
} | ||
} | ||
|
||
return res; | ||
} | ||
|
||
function getDelegatedPowerByMe(address _to) public view returns(uint) { | ||
function getDelegatedPowerByMe(address _to, uint _votingID) public view returns(uint) { | ||
uint res; | ||
|
||
for(uint i = 0; i < delegations[msg.sender].length; i++){ | ||
if(delegations[msg.sender][i]._address == _to){ | ||
if(delegations[msg.sender][i].isDelegator){ | ||
res += delegations[msg.sender][i].amount; | ||
for(uint i = 0; i < delegations[_votingID][msg.sender].length; i++){ | ||
if(delegations[_votingID][msg.sender][i]._address == _to){ | ||
if(delegations[_votingID][msg.sender][i].isDelegator){ | ||
res += delegations[_votingID][msg.sender][i].amount; | ||
} | ||
} | ||
} | ||
|
||
return res; | ||
} | ||
|
||
function delegateMyVoiceTo(address _to, uint _tokenAmount) public { | ||
function delegateMyVoiceTo(address _to, uint _tokenAmount, uint _votingID) public { | ||
require (_to!= address(0)); | ||
require (_tokenAmount <= stdDaoToken.getBalanceAtVoting(votingID, msg.sender)); | ||
|
||
for(uint i = 0; i < delegations[_to].length; i++){ | ||
if(delegations[_to][i]._address == msg.sender){ | ||
delegations[_to][i].amount = _tokenAmount; | ||
for(uint i = 0; i < delegations[_votingID][_to].length; i++){ | ||
if(delegations[_votingID][_to][i]._address == msg.sender){ | ||
delegations[_votingID][_to][i].amount = _tokenAmount; | ||
} | ||
} | ||
|
||
for(i = 0; i < delegations[msg.sender].length; i++){ | ||
if(delegations[msg.sender][i]._address == _to){ | ||
delegations[msg.sender][i].amount = _tokenAmount; | ||
for(i = 0; i < delegations[_votingID][msg.sender].length; i++){ | ||
if(delegations[_votingID][msg.sender][i]._address == _to){ | ||
delegations[_votingID][msg.sender][i].amount = _tokenAmount; | ||
emit DelegatedTo(_to, _tokenAmount); | ||
return; | ||
} | ||
} | ||
|
||
delegations[_to].push(Delegation(msg.sender, _tokenAmount, false)); | ||
delegations[msg.sender].push(Delegation(_to, _tokenAmount, true)); | ||
delegations[_votingID][_to].push(Delegation(msg.sender, _tokenAmount, false)); | ||
delegations[_votingID][msg.sender].push(Delegation(_to, _tokenAmount, true)); | ||
} | ||
|
||
function removeDelegation(address _to) public { | ||
function removeDelegation(address _to, uint _votingID) public { | ||
require (_to!= address(0)); | ||
|
||
for(uint i = 0; i < delegations[_to].length; i++){ | ||
if(delegations[_to][i]._address == msg.sender){ | ||
delegations[_to][i].amount = 0; | ||
for(uint i = 0; i < delegations[_votingID][_to].length; i++){ | ||
if(delegations[_votingID][_to][i]._address == msg.sender){ | ||
delegations[_votingID][_to][i].amount = 0; | ||
} | ||
} | ||
|
||
for(i = 0; i < delegations[msg.sender].length; i++){ | ||
if(delegations[msg.sender][i]._address == _to){ | ||
delegations[msg.sender][i].amount = 0; | ||
for(i = 0; i < delegations[_votingID][msg.sender].length; i++){ | ||
if(delegations[_votingID][msg.sender][i]._address == _to){ | ||
delegations[_votingID][msg.sender][i].amount = 0; | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Почему тут 0? А что если голосование не первое запущенное. Это не будет работать, правильно?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Да, правильно. Это заглушка чтобы не лезть дальше