splitDAOの実行可能条件について


混乱が多いので解説。自分もよくわかってなかった・・。


コード参照元
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実行できません

3. キュレーターと受取人は同じかどうか： p.recipient != _newCurator


4. 新しいキュレーターによるproposalかどうか　：!p.newCurator
 * newCurator=trueのproposalでしかsplitは有効ではない

5. YESに投票したかどうか：!p.votedYes[msg.sender]
  * msg.senderはトランザクションを送った人のアドレス。
  * splitDAOの実行者（各トークンホルダー）
  * p.votedYes[msg.sender]は、YESに投票した人はtrueの値が入っている。
  * !p.votedYes[msg.sender]なので投票した人はfalseになる。投票してない人、Noだった人はtrueになりsplit実行できない

6. 他のproposalによってblock状態かどうか：　(blocked[msg.sender] != _proposalID && blocked[msg.sender] != 0)

 * アカウントが他の投票参加中でblockされてるとsplitDAOが実行できない。



##以上６つの条件です。

* 下手に同一アカウントで投票しまくったりすると投票期間中blockされるのでアカウント分けて投票するのがいいのでしょう。splitは一個に対してしかできませんし・・・。

* YESに投じてない人は可決されたsplitに参加できない！！ということを知ったので、ちゃんと投票しないといけないのかーーーーーーーーーーー