混乱が多いので解説。自分もよくわかってなかった・・。
コード参照元
https://github.com/slockit/DAO/blob/master/DAO.sol
DAO.sol
625-698行目を抜粋
function splitDAO(
uint _proposalID,
address _newCurator
) noEther onlyTokenholders returns (bool _success) {
Proposal p = proposals[_proposalID];
// Sanity check
if (now < p.votingDeadline // has the voting deadline arrived?
//The request for a split expires XX days after the voting deadline
|| now > p.votingDeadline + splitExecutionPeriod
// Does the new Curator address match?
|| p.recipient != _newCurator
// Is it a new curator proposal?
|| !p.newCurator
// Have you voted for this split?
|| !p.votedYes[msg.sender]
// Did you already vote on another proposal?
|| (blocked[msg.sender] != _proposalID && blocked[msg.sender] != 0) ) {
throw;
}
// If the new DAO doesn't exist yet, create the new DAO and store the
// current split data
if (address(p.splitData[0].newDAO) == 0) {
p.splitData[0].newDAO = createNewDAO(_newCurator);
// Call depth limit reached, etc.
if (address(p.splitData[0].newDAO) == 0)
throw;
// should never happen
if (this.balance < sumOfProposalDeposits)
throw;
p.splitData[0].splitBalance = actualBalance();
p.splitData[0].rewardToken = rewardToken[address(this)];
p.splitData[0].totalSupply = totalSupply;
p.proposalPassed = true;
}
// Move ether and assign new Tokens
uint fundsToBeMoved =
(balances[msg.sender] * p.splitData[0].splitBalance) /
p.splitData[0].totalSupply;
if (p.splitData[0].newDAO.createTokenProxy.value(fundsToBeMoved)(msg.sender) == false)
throw;
// Assign reward rights to new DAO
uint rewardTokenToBeMoved =
(balances[msg.sender] * p.splitData[0].rewardToken) /
p.splitData[0].totalSupply;
uint paidOutToBeMoved = DAOpaidOut[address(this)] * rewardTokenToBeMoved /
rewardToken[address(this)];
rewardToken[address(p.splitData[0].newDAO)] += rewardTokenToBeMoved;
if (rewardToken[address(this)] < rewardTokenToBeMoved)
throw;
rewardToken[address(this)] -= rewardTokenToBeMoved;
DAOpaidOut[address(p.splitData[0].newDAO)] += paidOutToBeMoved;
if (DAOpaidOut[address(this)] < paidOutToBeMoved)
throw;
DAOpaidOut[address(this)] -= paidOutToBeMoved;
// Burn DAO Tokens
Transfer(msg.sender, 0, balances[msg.sender]);
withdrawRewardFor(msg.sender); // be nice, and get his rewards
totalSupply -= balances[msg.sender];
balances[msg.sender] = 0;
paidOut[msg.sender] = 0;
return true;
}
Sanity checkが実行権限チェックのところです
// Sanity check
if (now < p.votingDeadline // has the voting deadline arrived?
//The request for a split expires XX days after the voting deadline
|| now > p.votingDeadline + splitExecutionPeriod
// Does the new Curator address match?
|| p.recipient != _newCurator
// Is it a new curator proposal?
|| !p.newCurator
// Have you voted for this split?
|| !p.votedYes[msg.sender]
// Did you already vote on another proposal?
|| (blocked[msg.sender] != _proposalID && blocked[msg.sender] != 0) ) {
throw;
}
ここで、if()の中で複数の条件があります。||はorの意味で、それらの条件のどれか一つでもtrueなると、
throw;
されて(エラーが発生してコントラクト実行停止)しまいます。
条件を見てみる
1.このsplitの投票は終了したか: now < p.votingDeadline
- nowは現在時刻を表す
- いまが投票終了日時より前の時は、true、投票終了後ならfalse
2.split可能期間を過ぎているかどうか : now > p.votingDeadline + splitExecutionPeriod
- split期限を過ぎたらtrueになりsplit実行できません
キュレーターと受取人は同じかどうか: p.recipient != _newCurator
-
新しいキュレーターによるproposalかどうか :!p.newCurator
- newCurator=trueのproposalでしかsplitは有効ではない
-
YESに投票したかどうか:!p.votedYes[msg.sender]
- msg.senderはトランザクションを送った人のアドレス。
- splitDAOの実行者(各トークンホルダー)
- p.votedYes[msg.sender]は、YESに投票した人はtrueの値が入っている。
- !p.votedYes[msg.sender]なので投票した人はfalseになる。投票してない人、Noだった人はtrueになりsplit実行できない
他のproposalによってblock状態かどうか: (blocked[msg.sender] != _proposalID && blocked[msg.sender] != 0)
- アカウントが他の投票参加中でblockされてるとsplitDAOが実行できない。
以上6つの条件です。
下手に同一アカウントで投票しまくったりすると投票期間中blockされるのでアカウント分けて投票するのがいいのでしょう。splitは一個に対してしかできませんし・・・。
YESに投じてない人は可決されたsplitに参加できない!!ということを知ったので、ちゃんと投票しないといけないのかーーーーーーーーーーー