Create WeiFundV2.sol

Create WeiFundV2.sol

// WeiFund v0.2
// Start, donate, payout and refund crowdfunding campaigns
contract WeiFundConfig
{
    function onNewCampaign(uint cid, address addr, uint goal){}
    function onContribute(uint cid, address addr, uint amount){}
    function onRefund(uint cid, address addr, uint amount){}
    function onPayout(uint cid, uint amount){}
}

/// @title WeiFund - A Decentralized Crowdfunding Platform
/// @author Nick Dodson <thenickdodson@gmail.com>
contract WeiFund
{
    // @notice User; This object stores the campaign operator data
    // @dev This object stores all pertinant campaign operator data, such as how many campaigns the operator has started, and the campaign ID's of all the campaigns they have or are operating
    struct User
    {
        uint numCampaigns;
        mapping(uint => uint) campaigns;
    }

    // @notice Funder; This object helps store the pertinant contributer data.
    // @dev This object stores the contributer data, such as the contributer address, and amount.
    struct Funder
    {
        address from;
        address addr;
        uint amount;
    }

    // @notice Campaign; The crowdfunding campaign object
    // @dev This object stores all the pertinant campaign data, such as: the name, beneificary, fundingGoal, and the funder data.
    struct Campaign
    {
        bytes32 name;
        bytes32 website;
        bytes32 video;
        address owner;
        address beneficiary;
        address config;
        uint timelimit;
        uint fundingGoal;
        uint amount;
        uint category;
        uint status;
        uint numFunders;
        mapping (uint => Funder) funders;
        mapping (address => uint) toFunder;
    }

    /// @notice numCampaigns; The total number of crowdfunding campaigns started on WeiFund
    /// @dev This is the uint store that contains the number of the total amount of all crowdfunding campaigns started on WeiFund. This is also used to generate campaign ID numbers.
    uint public numCampaigns;

    /// @notice Campaigns (the campaign ID); Get the campaign data at the specified campaign ID
    /// @dev This data store maps campaign ID's to stored Campaign objects. With this method you can access any crowdfunding campaign started on WeiFund.
    mapping (uint => Campaign) public campaigns;

    /// @notice Users (the user address); Get the number of campaigns a user has started
    /// @dev This will return a user object that contains the number of campaigns a user has started. Use the userCampaigns method to the ID's to the crowdfunding campaigns that they have started.
    mapping (address => User) public users;

    // The WeiFund Events
    event onNewCampaign(address indexed _from, uint indexed _cid);
    event onContribute(address indexed _from, uint indexed _cid, uint _value);
    event onPayout(address indexed _from, uint indexed _cid, uint _value);
    event onRefund(address indexed _from, uint indexed _cid, uint _value);

    modifier hasValue { if(msg.value > 0) _ }

    /// @notice New Campaign; create a new crowdfunding campaign
    /// @dev This method starts a new crowdfunding campaign and fires the onNewCampaign event when transacted.
    /// @param _name The campaign name
    /// @param _website The website of the crowdfunding campaign
    /// @param _video The compressed video url (e.g. yt JFdi289d)
    /// @param _beneficiary The address of the beneficiary for this campaign
    /// @param _goal The funding goal of the campaign. If this goal is not met by the timelimit, all ether will be refunded to the respective contributers
    /// @param _timelimit The timelimit for the campaign
    /// @param _category The category ID for the crowdfunding campaign (e.g. 2: Technology)
    /// @param _config
    function newCampaign(bytes32 _name, bytes32 _website, bytes32 _video
    , address _beneficiary, uint _goal, uint _timelimit, uint _category, address _config)
    {
        if(_goal > 0 && _timelimit > now){
            uint cid = numCampaigns++; // campaignID is return variable
            Campaign c = campaigns[cid];  // assigns reference
            c.name = _name;
            c.website = _website;
            c.video = _video;
            c.owner = msg.sender;
            c.beneficiary = _beneficiary;
            c.fundingGoal = _goal;
            c.timelimit = _timelimit;
            c.category = _category;
            c.config = _config;

            User u = users[msg.sender];
            uint u_cid = u.numCampaigns++;
            u.campaigns[u_cid] = cid;

            onNewCampaign(msg.sender, cid);

            if(c.config != address(0))
                WeiFundConfig(c.config).onNewCampaign(cid, msg.sender, _goal);
        }
    }

    /// @notice Contribute (the campaign ID); contribute ether to a WeiFund campaign
    /// @dev This method will contribute an amount of ether to the campaign at ID _cid. All contribution data will be stored so that the issuance of digital assets can be made out to the contributor address
    /// @param _cid (Campaign ID) The ID number of the crowdfunding campaign
    /// @param _addr (Contribute As Address) This allows a user to contribute on behalf of another address, if left empty, the from sender address is used as the primary Funder address
    function contribute(uint _cid, address _addr) hasValue
    {
        Campaign c = campaigns[_cid]; // Cannot be expired.
        if(c.timelimit >= block.timestamp){
            if(c.config != address(0)
              && !WeiFundConfig(c.config).onContribute(_cid, msg.sender, msg.value))
              return;

            uint fid = c.numFunders++;
            Funder f = c.funders[fid];
            f.from = msg.sender;
            f.addr = _addr;
            f.amount = msg.value;
            c.amount += f.amount;
            c.toFunder[msg.sender] = fid;
            onContribute(msg.sender, _cid, c.amount);
        }
    }

    /// @notice Refund (the campaign ID); refund your contribution of a failed or expired crowdfunding campaign.
    /// @dev This method will refund the amount you contributed to a WeiFund campaign, if that campaign has failed to meet it's funding goal or has expired.
    /// @param _cid (Campaign ID) The ID number of the crowdfunding campaign to be refunded
    function refund(uint _cid)
    {
        Campaign c = campaigns[_cid];
        if (block.timestamp > c.timelimit
        && c.amount < c.fundingGoal && c.amount > 0){
            Funder f = c.funders[c.toFunder[msg.sender]];
            if(f.amount > 0){
                address recv = f.from;

                if(f.addr != address(0))
                    recv = f.addr;

                if(c.config != address(0)
                  && !WeiFundConfig(c.config).onRefund(_cid, recv, f.amount))
                  return;

                recv.send(f.amount);
                c.amount -= f.amount;
                onRefund(recv, _cid, f.amount);
                f.amount = 0;
            }
        }
    }

    /// @notice Payout (the campaign ID); this will payout a successfull crowdfunding campaign to the benificiary address
    /// @dev This method will payout a successfull WeiFund crowdfunding campaign to the benificiary address specified. Any person can trigger the payout by calling this method.
    /// @param _cid (Campaign ID) The ID number of the crowdfunding campaign
    function payout(uint _cid)
    {
        Campaign c = campaigns[_cid];
        if (c.amount >= c.fundingGoal){
            c.beneficiary.send(c.amount);
            onPayout(msg.sender, _cid, c.amount);
            c.amount = 0;
            c.status = 1;

            if(c.config != address(0))
                WeiFundConfig(c.config).onPayout(_cid, c.amount);
        }
    }

    /// @notice User Campaigns (the address of the user, the user campaign ID); get the campaign ID of one of the users crowdfunding campaigns.
    /// @dev This method will get the campaign ID of one of the users crowdfunding campaigns, by looking up the campaign with a user campaign ID. All campaign owners and their campaigns are stored with WeiFund.
    /// @param _addr The address of the campaign operator.
    /// @param _u_cid The user campaign ID
    /// @return cid The campaign ID
    function userCampaigns(address _addr, uint _u_cid) returns (uint cid)
    {
        User u = users[_addr];
        cid = u.campaigns[_u_cid];
    }
}

error: pathspec 'contracts/WeiFundV2.sol' did not match any file(s) known to git


fixed typo in modifier name

fixed typo in modifier name

import "Token.sol";

library NettingChannelLibrary {
    struct Lock
    {
        uint64 expiration;
        uint amount;
        bytes32 hashlock;
    }

    struct Participant
    {
        address nodeAddress;
        uint256 balance;
        uint256 netted;
        uint256 transferedAmount;
        uint256 amount;
        bytes merkleProof;
        bytes32 hashlock;
        bytes32 secret;
        uint256 expiration;
        uint64 nonce;
        address asset;
        address recipient;
        bytes32 locksroot;
        Lock[] unlocked;
    }

    struct Data {
        uint settleTimeout;
        uint opened;
        uint closed;
        uint settled;
        address closingAddress;
        Token token;
        Participant[2] participants;
    }

    modifier notSettledButClosed(Data storage self) {
        if (self.settled > 0 || self.closed == 0)
            throw;
        _
    }

    modifier stillTimeout(Data storage self) {
        if (self.closed + self.settleTimeout < block.number)
            throw;
        _
    }

    /// @notice deposit(uint) to deposit amount to channel.
    /// @dev Deposit an amount to the channel. At least one of the participants
    /// must deposit before the channel is opened.
    /// @param amount (uint) the amount to be deposited to the address
    function deposit(Data storage self, address callerAddress, address channelAddress, uint256 amount) returns (bool success, uint256 balance) {
        uint index;

        if (self.closed != 0) {
            throw;
        }

        if (self.token.balanceOf(callerAddress) < amount) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage participant = participants[0];
        if (participant.nodeAddress != callerAddress) {
            participant = participants[1];
            if (participant.nodeAddress != callerAddress) {
                throw;
            }
        }

        success = self.token.transferFrom(
            callerAddress,
            channelAddress,
            amount
        );

        if (success == true) {
            balance = participant.balance;
            balance += amount;
            participant.balance = balance;

            if (self.opened == 0) {
                self.opened = block.number;
            }

            return (true, balance);
        }

        return (false, 0);
    }

    /// @notice partner() to get the partner or other participant of the channel
    /// @dev Get the other participating party of the channel
    /// @return partnerAddress (address) the partner of the calling party
    function partner(Data storage self, address one_address) constant returns (address) {
        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (one_address == node1.nodeAddress) {
            return node2.nodeAddress;
        }

        if (one_address == node2.nodeAddress) {
            return node1.nodeAddress;
        }

        return 0x0;
    }

    function addressAndBalance(Data storage self) constant returns (address participant1, uint balance1, address participant2, uint balance2) {
        Participant[2] participants = self.participants;
        Participant node1 = participants[0];
        Participant node2 = participants[1];

        // return by name
        participant1 = node1.nodeAddress;
        balance1 = node1.balance;
        participant2 = node2.nodeAddress;
        balance2 = node2.balance;
    }

    function closeSingleTransfer(Data storage self, address callerAddress, bytes signed_transfer) {
        bytes memory transfer_raw;
        address transfer_address;

        if (self.settled > 0 || self.closed > 0) {
            throw;
        }

        if (signed_transfer.length <= 65) {
            throw;
        }

        (transfer_raw, transfer_address) = getTransferRawAddress(signed_transfer);

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (callerAddress != node1.nodeAddress && callerAddress != node2.nodeAddress) {
            throw;
        }

        if (node1.nodeAddress == transfer_address) {
            Participant storage sender = node1;
        } else if (node2.nodeAddress == transfer_address) {
            sender = node2;
        } else {
            throw;
        }

        decode_and_assign(sender, transfer_raw);

        self.closingAddress = callerAddress;
        self.closed = block.number;

        // TODO: penalize
        // uint allowance, difference, transfered_amount;
        // transfered_amount = sender.transferedAmount;
        // allowance = node1.balance + node2.balance;
        // if(amount1 > amount2) {
        //     difference = amount1 - amount2;
        // } else {
        //     difference = amount2 - amount1;
        // }
        // if (difference > allowance) {
        //     penalize();
        // }
    }

    /// @notice close(bytes, bytes) to close a channel between to parties
    /// @dev Close the channel between two parties
    /// @param firstEncoded (bytes) the last sent transfer of the msg.sender
    /// @param secondEncoded (bytes) the last sent transfer of the msg.sender
    function close(Data storage self, address callerAddress, bytes firstEncoded, bytes secondEncoded) {
        bytes memory first_raw;
        bytes memory second_raw;
        address first_address;
        address second_address;
        bytes32 transfer_sender;

        if (self.settled > 0 || self.closed > 0) {
            throw;
        }

        if (firstEncoded.length <= 65 || secondEncoded.length <= 65) {
            throw;
        }

        (first_raw, first_address) = getTransferRawAddress(firstEncoded);
        (second_raw, second_address) = getTransferRawAddress(secondEncoded);

        if (first_address == second_address) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (callerAddress != node1.nodeAddress && callerAddress != node2.nodeAddress) {
            throw;
        }

        if (node1.nodeAddress == first_address) {
            Participant storage first_sender = node1;
        } else if (node2.nodeAddress == first_address) {
            first_sender = node2;
        } else {
            throw;
        }

        if (node1.nodeAddress == second_address) {
            Participant storage second_sender = node1;
        } else if (node2.nodeAddress == second_address) {
            second_sender = node2;
        } else {
            throw;
        }

        decode_and_assign(first_sender, first_raw);
        decode_and_assign(second_sender, second_raw);

        self.closingAddress = callerAddress;
        self.closed = block.number;

        // TODO: penalize
        // uint allowance, difference, amount1, amount2;
        // amount1 = node1.transferedAmount;
        // amount2 = node2.transferedAmount;
        // allowance = node1.balance + node2.balance;
        // if(amount1 > amount2) {
        //     difference = amount1 - amount2;
        // } else {
        //     difference = amount2 - amount1;
        // }
        // if (difference > allowance) {
        //     penalize();
        // }
    }

    /// @notice updateTransfer(bytes) to update last known transfer
    /// @dev Allow the partner to update the last known transfer
    function updateTransfer(Data storage self, address callerAddress, bytes signed_transfer) {
        uint64 nonce;
        bytes memory transfer_raw;
        address transfer_address;

        if (self.settled > 0 || self.closed == 0) {
            throw;
        }

        if (self.closed + self.settleTimeout < block.number) {
            throw;
        }

        (transfer_raw, transfer_address) = getTransferRawAddress(signed_transfer);

        // participant that called close cannot update
        if (self.closingAddress == transfer_address) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (node1.nodeAddress == transfer_address) {
            Participant storage sender = node1;
        } else if (node2.nodeAddress == transfer_address) {
            sender = node2;
        } else {
            throw;
        }

        assembly {
            nonce := mload(add(transfer_raw, 12))  // skip cmdid and padding
        }

        if (nonce < sender.nonce) {
            throw;
        }

        decode_and_assign(sender, transfer_raw);

        // TODO check if tampered and penalize
        // TODO check if outdated and penalize
    }

    /// @notice unlock(bytes, bytes, bytes32) to unlock a locked transfer
    /// @dev Unlock a locked transfer
    /// @param lockedEncoded (bytes) the lock
    /// @param merkleProof (bytes) the merkle proof
    /// @param secret (bytes32) the secret
    function unlock(Data storage self, address callerAddress, bytes lockedEncoded, bytes merkleProof, bytes32 secret) {
        uint partnerId;
        uint64 expiration;
        uint amount;
        bytes32 hashlock;
        bytes32 h;
        bytes32 el;

        if (self.settled > 0 || self.closed == 0) {
            throw;
        }

        (expiration, amount, hashlock) = decodeLock(lockedEncoded);

        if (expiration > self.closed) {
            throw;
        }

        if (hashlock != sha3(secret)) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage participant = participants[0];
        if (participant.nodeAddress != callerAddress) {
            participant = participants[1];
            if (participant.nodeAddress != callerAddress) {
                throw;
            }
        }

        if (participant.nonce == 0) {
            throw;
        }

        h = sha3(lockedEncoded);
        for (uint i = 32; i <= merkleProof.length; i += 32) {
            assembly {
                el := mload(add(merkleProof, i))
            }

            if (h < el) {
                h = sha3(h, el);
            } else {
                h = sha3(el, h);
            }
        }

        // TODO
        // if (participant.locksroot != h) {
        //   throw;
        // }

        participant.unlocked.push(Lock(expiration, amount, hashlock));
    }

    /// @notice settle() to settle the balance between the two parties
    /// @dev Settles the balances of the two parties fo the channel
    /// @return participants (Participant[2]) the participants with netted balances
    function settle(Data storage self, address callerAddress)
        notSettledButClosed(self)
        stillTimeout(self)
    {
        uint totalNetted;
        uint totalDeposit;
        uint k;

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        node1.netted = node1.balance + node2.transferedAmount - node1.transferedAmount;
        node2.netted = node2.balance + node1.transferedAmount - node2.transferedAmount;

        for (k=0; k < node1.unlocked.length; k++) {
            node1.netted += node1.unlocked[k].amount;
            node2.netted -= node1.unlocked[k].amount;
        }

        for (k=0; k < node2.unlocked.length; k++) {
            node2.netted += node2.unlocked[k].amount;
            node1.netted -= node2.unlocked[k].amount;
        }

        self.settled = block.number;

        totalNetted = node1.netted + node2.netted;
        totalDeposit = node1.balance + node2.balance;

        if (totalNetted != totalDeposit) {
            throw;
        }

        self.token.transfer(node1.nodeAddress, node1.netted);
        self.token.transfer(node2.nodeAddress, node2.netted);
    }

    function getTransferRawAddress(bytes memory signed_transfer) private returns (bytes memory, address) {
        uint signature_start;
        uint length;
        bytes memory signature;
        bytes memory transfer_raw;
        bytes32 transfer_hash;
        address transfer_address;

        length = signed_transfer.length;
        signature_start = length - 65;
        signature = slice(signed_transfer, signature_start, length);
        transfer_raw = slice(signed_transfer, 0, signature_start);

        transfer_hash = sha3(transfer_raw);
        var (r, s, v) = signature_split(signature);
        transfer_address = ecrecover(transfer_hash, v, r, s);

        return (transfer_raw, transfer_address);
    }

    function decode_and_assign(Participant storage sender, bytes transfer_raw) private {
        // all checks must be done by now
        uint cmdid;

        cmdid = uint(transfer_raw[0]);

        if (cmdid == 5) {
            assignDirectTransfer(sender, transfer_raw);
        } else if (cmdid == 7) {
            assignMediatedTransfer(sender, transfer_raw);
        } else if (cmdid == 8) {
            assignRefundTransfer(sender, transfer_raw);
        } else {
            throw;
        }
    }

    // notes:
    // about the length of variable types:
    //  - inside an assembly block a type of `bytes memory` works as a pointer to
    //  memory, since bytes is variable size it follows the ethereum contract
    //  abi.
    //  - all variable length types start with a size-prefix of type uint256, so
    //  the 256bits/32bytes represent the length of the object.
    //  - the variable start pointing in the last byte of the length
    // - pointer arithmetic works on a byte basis, to `add(var, 1)` will advance
    // 1 byte.
    // - the pointer should be at the _last_ byte of the value, mload loads
    // values from higher-to-lower addresses

    // TODO: use sstore instead of these temporaries

    function assignDirectTransfer(Participant storage participant, bytes memory message) private {
        if (message.length != 148) {  // raw message size (without signature)
            throw;
        }

        uint64 nonce;
        address asset;
        address recipient;
        uint256 transferedAmount;
        bytes32 locksroot;
        bytes32 secret;

        assembly {
            // cmdid [0:1]
            // pad [1:4]
            nonce := mload(add(message, 12))            // nonce [4:12]
            asset := mload(add(message, 32))            // asset [12:32]
            recipient := mload(add(message, 52))        // recipient [32:52]
            transferedAmount := mload(add(message, 84)) // transfered_amount [52:84]
            locksroot := mload(add(message, 116))       // optional_locksroot [84:116]
            secret := mload(add(message, 148))          // optional_secret [116:158]
        }

        participant.nonce = nonce;
        participant.asset = asset;
        participant.recipient = recipient;
        participant.transferedAmount = transferedAmount;
        participant.locksroot = locksroot;
        participant.secret = secret;
    }

    function assignMediatedTransfer(Participant storage participant, bytes memory message) private {
        if (message.length != 325) {
            throw;
        }

        uint64 nonce;
        uint64 expiration;
        address asset;
        address recipient;
        bytes32 locksroot;
        bytes32 hashlock;
        uint256 transferedAmount;
        uint256 lockAmount;

        assembly {
            // cmdid [0:1]
            // pad [1:4]
            nonce := mload(add(message, 12))        // nonce [4:12]
            expiration := mload(add(message, 20))   // expiration [12:20]
            asset := mload(add(message, 40))        // asset [20:40]
            recipient := mload(add(message, 60))    // recipient [40:60]
            // target [60:80]
            // initiator [80:100]
            locksroot := mload(add(message, 132))   // locksroot [100:132]
            hashlock := mload(add(message, 164))    // hashlock [100:164]
            transferedAmount := mload(add(message, 196)) // transfered_amount[164:196]
            lockAmount := mload(add(message, 228))  // amount [196:228]
            // fee := mload(add(message, 260))      // fee [228:260]
        }

        participant.nonce = nonce;
        participant.expiration = expiration;
        participant.asset = asset;
        participant.recipient = recipient;
        participant.locksroot = locksroot;
        participant.hashlock = hashlock;
        participant.transferedAmount = transferedAmount;
        participant.amount = lockAmount;
    }

    function assignRefundTransfer(Participant storage participant, bytes memory message) private {
        if (message.length != 253) {
            throw;
        }

        uint64 nonce;
        uint64 expiration;
        address asset;
        address recipient;
        bytes32 locksroot;
        uint256 transferedAmount;
        uint256 lockAmount;
        bytes32 hashlock;

        assembly {
            // cmdid [0:1]
            // pad [1:4]
            nonce := mload(add(message, 12))        // nonce [4:12]
            expiration := mload(add(message, 20))   // expiration [12:20]
            asset := mload(add(message, 40))        // asset [20:40]
            recipient := mload(add(message, 60))    // recipient [40:60]
            locksroot := mload(add(message, 92))    // locksroot [60:92]
            transferedAmount := mload(add(message, 124)) // transfered_amount [92:124]
            lockAmount := mload(add(message, 156))  // amount [124:156]
            hashlock := mload(add(message, 188))    // hashlock [156:188]
        }

        participant.nonce = nonce;
        participant.expiration = expiration;
        participant.asset = asset;
        participant.recipient = recipient;
        participant.locksroot = locksroot;
        participant.transferedAmount = transferedAmount;
        participant.amount = lockAmount;
        participant.hashlock = hashlock;
    }

    function decodeLock(bytes lock) private returns (uint64 expiration, uint amount, bytes32 hashlock) {
        if (lock.length != 72) {
            throw;
        }

        assembly {
            expiration := mload(add(lock, 8))   // expiration [0:8]
            amount := mload(add(lock, 40))      // expiration [8:40]
            hashlock := mload(add(lock, 72))    // expiration [40:72]

        }
    }

    function signature_split(bytes signature) private returns (bytes32 r, bytes32 s, uint8 v) {
        // The signature format is a compact form of:
        //   {bytes32 r}{bytes32 s}{uint8 v}
        // Compact means, uint8 is not padded to 32 bytes.
        assembly {
            r := mload(add(signature, 32))
            s := mload(add(signature, 64))
            // Here we are loading the last 32 bytes, including 31 bytes
            // of 's'. There is no 'mload8' to do this.
            //
            // 'byte' is not working due to the Solidity parser, so lets
            // use the second best option, 'and'
            v := and(mload(add(signature, 65)), 1)
        }
        // old geth sends a `v` value of [0,1], while the new, in line with the YP sends [27,28]
        if(v < 27) v += 27;
    }

    function slice(bytes a, uint start, uint end) private returns (bytes n) {
        if (a.length < end) {
            throw;
        }
        if (start < 0) {
            throw;
        }

        n = new bytes(end-start);
        for ( uint i = start; i < end; i ++) { //python style slice
            n[i-start] = a[i];
        }
    }

    function () { throw; }
}

import "Token.sol";

library NettingChannelLibrary {
    struct Lock
    {
        uint64 expiration;
        uint amount;
        bytes32 hashlock;
    }

    struct Participant
    {
        address nodeAddress;
        uint256 balance;
        uint256 netted;
        uint256 transferedAmount;
        uint256 amount;
        bytes merkleProof;
        bytes32 hashlock;
        bytes32 secret;
        uint256 expiration;
        uint64 nonce;
        address asset;
        address recipient;
        bytes32 locksroot;
        Lock[] unlocked;
    }

    struct Data {
        uint settleTimeout;
        uint opened;
        uint closed;
        uint settled;
        address closingAddress;
        Token token;
        Participant[2] participants;
    }

    modifier notSettledButClosed(Data storage self) {
        if (self.settled > 0 || self.closed == 0)
            throw;
        _
    }

    modifier stillTimout(Data storage self) {
        if (self.closed + self.settleTimeout < block.number)
            throw;
        _
    }

    /// @notice deposit(uint) to deposit amount to channel.
    /// @dev Deposit an amount to the channel. At least one of the participants
    /// must deposit before the channel is opened.
    /// @param amount (uint) the amount to be deposited to the address
    function deposit(Data storage self, address callerAddress, address channelAddress, uint256 amount) returns (bool success, uint256 balance) {
        uint index;

        if (self.closed != 0) {
            throw;
        }

        if (self.token.balanceOf(callerAddress) < amount) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage participant = participants[0];
        if (participant.nodeAddress != callerAddress) {
            participant = participants[1];
            if (participant.nodeAddress != callerAddress) {
                throw;
            }
        }

        success = self.token.transferFrom(
            callerAddress,
            channelAddress,
            amount
        );

        if (success == true) {
            balance = participant.balance;
            balance += amount;
            participant.balance = balance;

            if (self.opened == 0) {
                self.opened = block.number;
            }

            return (true, balance);
        }

        return (false, 0);
    }

    /// @notice partner() to get the partner or other participant of the channel
    /// @dev Get the other participating party of the channel
    /// @return partnerAddress (address) the partner of the calling party
    function partner(Data storage self, address one_address) constant returns (address) {
        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (one_address == node1.nodeAddress) {
            return node2.nodeAddress;
        }

        if (one_address == node2.nodeAddress) {
            return node1.nodeAddress;
        }

        return 0x0;
    }

    function addressAndBalance(Data storage self) constant returns (address participant1, uint balance1, address participant2, uint balance2) {
        Participant[2] participants = self.participants;
        Participant node1 = participants[0];
        Participant node2 = participants[1];

        // return by name
        participant1 = node1.nodeAddress;
        balance1 = node1.balance;
        participant2 = node2.nodeAddress;
        balance2 = node2.balance;
    }

    function closeSingleTransfer(Data storage self, address callerAddress, bytes signed_transfer) {
        bytes memory transfer_raw;
        address transfer_address;

        if (self.settled > 0 || self.closed > 0) {
            throw;
        }

        if (signed_transfer.length <= 65) {
            throw;
        }

        (transfer_raw, transfer_address) = getTransferRawAddress(signed_transfer);

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (callerAddress != node1.nodeAddress && callerAddress != node2.nodeAddress) {
            throw;
        }

        if (node1.nodeAddress == transfer_address) {
            Participant storage sender = node1;
        } else if (node2.nodeAddress == transfer_address) {
            sender = node2;
        } else {
            throw;
        }

        decode_and_assign(sender, transfer_raw);

        self.closingAddress = callerAddress;
        self.closed = block.number;

        // TODO: penalize
        // uint allowance, difference, transfered_amount;
        // transfered_amount = sender.transferedAmount;
        // allowance = node1.balance + node2.balance;
        // if(amount1 > amount2) {
        //     difference = amount1 - amount2;
        // } else {
        //     difference = amount2 - amount1;
        // }
        // if (difference > allowance) {
        //     penalize();
        // }
    }

    /// @notice close(bytes, bytes) to close a channel between to parties
    /// @dev Close the channel between two parties
    /// @param firstEncoded (bytes) the last sent transfer of the msg.sender
    /// @param secondEncoded (bytes) the last sent transfer of the msg.sender
    function close(Data storage self, address callerAddress, bytes firstEncoded, bytes secondEncoded) {
        bytes memory first_raw;
        bytes memory second_raw;
        address first_address;
        address second_address;
        bytes32 transfer_sender;

        if (self.settled > 0 || self.closed > 0) {
            throw;
        }

        if (firstEncoded.length <= 65 || secondEncoded.length <= 65) {
            throw;
        }

        (first_raw, first_address) = getTransferRawAddress(firstEncoded);
        (second_raw, second_address) = getTransferRawAddress(secondEncoded);

        if (first_address == second_address) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (callerAddress != node1.nodeAddress && callerAddress != node2.nodeAddress) {
            throw;
        }

        if (node1.nodeAddress == first_address) {
            Participant storage first_sender = node1;
        } else if (node2.nodeAddress == first_address) {
            first_sender = node2;
        } else {
            throw;
        }

        if (node1.nodeAddress == second_address) {
            Participant storage second_sender = node1;
        } else if (node2.nodeAddress == second_address) {
            second_sender = node2;
        } else {
            throw;
        }

        decode_and_assign(first_sender, first_raw);
        decode_and_assign(second_sender, second_raw);

        self.closingAddress = callerAddress;
        self.closed = block.number;

        // TODO: penalize
        // uint allowance, difference, amount1, amount2;
        // amount1 = node1.transferedAmount;
        // amount2 = node2.transferedAmount;
        // allowance = node1.balance + node2.balance;
        // if(amount1 > amount2) {
        //     difference = amount1 - amount2;
        // } else {
        //     difference = amount2 - amount1;
        // }
        // if (difference > allowance) {
        //     penalize();
        // }
    }

    /// @notice updateTransfer(bytes) to update last known transfer
    /// @dev Allow the partner to update the last known transfer
    function updateTransfer(Data storage self, address callerAddress, bytes signed_transfer) {
        uint64 nonce;
        bytes memory transfer_raw;
        address transfer_address;

        if (self.settled > 0 || self.closed == 0) {
            throw;
        }

        if (self.closed + self.settleTimeout < block.number) {
            throw;
        }

        (transfer_raw, transfer_address) = getTransferRawAddress(signed_transfer);

        // participant that called close cannot update
        if (self.closingAddress == transfer_address) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        if (node1.nodeAddress == transfer_address) {
            Participant storage sender = node1;
        } else if (node2.nodeAddress == transfer_address) {
            sender = node2;
        } else {
            throw;
        }

        assembly {
            nonce := mload(add(transfer_raw, 12))  // skip cmdid and padding
        }

        if (nonce < sender.nonce) {
            throw;
        }

        decode_and_assign(sender, transfer_raw);

        // TODO check if tampered and penalize
        // TODO check if outdated and penalize
    }

    /// @notice unlock(bytes, bytes, bytes32) to unlock a locked transfer
    /// @dev Unlock a locked transfer
    /// @param lockedEncoded (bytes) the lock
    /// @param merkleProof (bytes) the merkle proof
    /// @param secret (bytes32) the secret
    function unlock(Data storage self, address callerAddress, bytes lockedEncoded, bytes merkleProof, bytes32 secret) {
        uint partnerId;
        uint64 expiration;
        uint amount;
        bytes32 hashlock;
        bytes32 h;
        bytes32 el;

        if (self.settled > 0 || self.closed == 0) {
            throw;
        }

        (expiration, amount, hashlock) = decodeLock(lockedEncoded);

        if (expiration > self.closed) {
            throw;
        }

        if (hashlock != sha3(secret)) {
            throw;
        }

        Participant[2] storage participants = self.participants;
        Participant storage participant = participants[0];
        if (participant.nodeAddress != callerAddress) {
            participant = participants[1];
            if (participant.nodeAddress != callerAddress) {
                throw;
            }
        }

        if (participant.nonce == 0) {
            throw;
        }

        h = sha3(lockedEncoded);
        for (uint i = 32; i <= merkleProof.length; i += 32) {
            assembly {
                el := mload(add(merkleProof, i))
            }

            if (h < el) {
                h = sha3(h, el);
            } else {
                h = sha3(el, h);
            }
        }

        // TODO
        // if (participant.locksroot != h) {
        //   throw;
        // }

        participant.unlocked.push(Lock(expiration, amount, hashlock));
    }

    /// @notice settle() to settle the balance between the two parties
    /// @dev Settles the balances of the two parties fo the channel
    /// @return participants (Participant[2]) the participants with netted balances
    function settle(Data storage self, address callerAddress)
        notSettledButClosed(self)
        stillTimout(self)
    {
        uint totalNetted;
        uint totalDeposit;
        uint k;

        Participant[2] storage participants = self.participants;
        Participant storage node1 = participants[0];
        Participant storage node2 = participants[1];

        node1.netted = node1.balance + node2.transferedAmount - node1.transferedAmount;
        node2.netted = node2.balance + node1.transferedAmount - node2.transferedAmount;

        for (k=0; k < node1.unlocked.length; k++) {
            node1.netted += node1.unlocked[k].amount;
            node2.netted -= node1.unlocked[k].amount;
        }

        for (k=0; k < node2.unlocked.length; k++) {
            node2.netted += node2.unlocked[k].amount;
            node1.netted -= node2.unlocked[k].amount;
        }

        self.settled = block.number;

        totalNetted = node1.netted + node2.netted;
        totalDeposit = node1.balance + node2.balance;

        if (totalNetted != totalDeposit) {
            throw;
        }

        self.token.transfer(node1.nodeAddress, node1.netted);
        self.token.transfer(node2.nodeAddress, node2.netted);
    }

    function getTransferRawAddress(bytes memory signed_transfer) private returns (bytes memory, address) {
        uint signature_start;
        uint length;
        bytes memory signature;
        bytes memory transfer_raw;
        bytes32 transfer_hash;
        address transfer_address;

        length = signed_transfer.length;
        signature_start = length - 65;
        signature = slice(signed_transfer, signature_start, length);
        transfer_raw = slice(signed_transfer, 0, signature_start);

        transfer_hash = sha3(transfer_raw);
        var (r, s, v) = signature_split(signature);
        transfer_address = ecrecover(transfer_hash, v, r, s);

        return (transfer_raw, transfer_address);
    }

    function decode_and_assign(Participant storage sender, bytes transfer_raw) private {
        // all checks must be done by now
        uint cmdid;

        cmdid = uint(transfer_raw[0]);

        if (cmdid == 5) {
            assignDirectTransfer(sender, transfer_raw);
        } else if (cmdid == 7) {
            assignMediatedTransfer(sender, transfer_raw);
        } else if (cmdid == 8) {
            assignRefundTransfer(sender, transfer_raw);
        } else {
            throw;
        }
    }

    // notes:
    // about the length of variable types:
    //  - inside an assembly block a type of `bytes memory` works as a pointer to
    //  memory, since bytes is variable size it follows the ethereum contract
    //  abi.
    //  - all variable length types start with a size-prefix of type uint256, so
    //  the 256bits/32bytes represent the length of the object.
    //  - the variable start pointing in the last byte of the length
    // - pointer arithmetic works on a byte basis, to `add(var, 1)` will advance
    // 1 byte.
    // - the pointer should be at the _last_ byte of the value, mload loads
    // values from higher-to-lower addresses

    // TODO: use sstore instead of these temporaries

    function assignDirectTransfer(Participant storage participant, bytes memory message) private {
        if (message.length != 148) {  // raw message size (without signature)
            throw;
        }

        uint64 nonce;
        address asset;
        address recipient;
        uint256 transferedAmount;
        bytes32 locksroot;
        bytes32 secret;

        assembly {
            // cmdid [0:1]
            // pad [1:4]
            nonce := mload(add(message, 12))            // nonce [4:12]
            asset := mload(add(message, 32))            // asset [12:32]
            recipient := mload(add(message, 52))        // recipient [32:52]
            transferedAmount := mload(add(message, 84)) // transfered_amount [52:84]
            locksroot := mload(add(message, 116))       // optional_locksroot [84:116]
            secret := mload(add(message, 148))          // optional_secret [116:158]
        }

        participant.nonce = nonce;
        participant.asset = asset;
        participant.recipient = recipient;
        participant.transferedAmount = transferedAmount;
        participant.locksroot = locksroot;
        participant.secret = secret;
    }

    function assignMediatedTransfer(Participant storage participant, bytes memory message) private {
        if (message.length != 325) {
            throw;
        }

        uint64 nonce;
        uint64 expiration;
        address asset;
        address recipient;
        bytes32 locksroot;
        bytes32 hashlock;
        uint256 transferedAmount;
        uint256 lockAmount;

        assembly {
            // cmdid [0:1]
            // pad [1:4]
            nonce := mload(add(message, 12))        // nonce [4:12]
            expiration := mload(add(message, 20))   // expiration [12:20]
            asset := mload(add(message, 40))        // asset [20:40]
            recipient := mload(add(message, 60))    // recipient [40:60]
            // target [60:80]
            // initiator [80:100]
            locksroot := mload(add(message, 132))   // locksroot [100:132]
            hashlock := mload(add(message, 164))    // hashlock [100:164]
            transferedAmount := mload(add(message, 196)) // transfered_amount[164:196]
            lockAmount := mload(add(message, 228))  // amount [196:228]
            // fee := mload(add(message, 260))      // fee [228:260]
        }

        participant.nonce = nonce;
        participant.expiration = expiration;
        participant.asset = asset;
        participant.recipient = recipient;
        participant.locksroot = locksroot;
        participant.hashlock = hashlock;
        participant.transferedAmount = transferedAmount;
        participant.amount = lockAmount;
    }

    function assignRefundTransfer(Participant storage participant, bytes memory message) private {
        if (message.length != 253) {
            throw;
        }

        uint64 nonce;
        uint64 expiration;
        address asset;
        address recipient;
        bytes32 locksroot;
        uint256 transferedAmount;
        uint256 lockAmount;
        bytes32 hashlock;

        assembly {
            // cmdid [0:1]
            // pad [1:4]
            nonce := mload(add(message, 12))        // nonce [4:12]
            expiration := mload(add(message, 20))   // expiration [12:20]
            asset := mload(add(message, 40))        // asset [20:40]
            recipient := mload(add(message, 60))    // recipient [40:60]
            locksroot := mload(add(message, 92))    // locksroot [60:92]
            transferedAmount := mload(add(message, 124)) // transfered_amount [92:124]
            lockAmount := mload(add(message, 156))  // amount [124:156]
            hashlock := mload(add(message, 188))    // hashlock [156:188]
        }

        participant.nonce = nonce;
        participant.expiration = expiration;
        participant.asset = asset;
        participant.recipient = recipient;
        participant.locksroot = locksroot;
        participant.transferedAmount = transferedAmount;
        participant.amount = lockAmount;
        participant.hashlock = hashlock;
    }

    function decodeLock(bytes lock) private returns (uint64 expiration, uint amount, bytes32 hashlock) {
        if (lock.length != 72) {
            throw;
        }

        assembly {
            expiration := mload(add(lock, 8))   // expiration [0:8]
            amount := mload(add(lock, 40))      // expiration [8:40]
            hashlock := mload(add(lock, 72))    // expiration [40:72]

        }
    }

    function signature_split(bytes signature) private returns (bytes32 r, bytes32 s, uint8 v) {
        // The signature format is a compact form of:
        //   {bytes32 r}{bytes32 s}{uint8 v}
        // Compact means, uint8 is not padded to 32 bytes.
        assembly {
            r := mload(add(signature, 32))
            s := mload(add(signature, 64))
            // Here we are loading the last 32 bytes, including 31 bytes
            // of 's'. There is no 'mload8' to do this.
            //
            // 'byte' is not working due to the Solidity parser, so lets
            // use the second best option, 'and'
            v := and(mload(add(signature, 65)), 1)
        }
        // old geth sends a `v` value of [0,1], while the new, in line with the YP sends [27,28]
        if(v < 27) v += 27;
    }

    function slice(bytes a, uint start, uint end) private returns (bytes n) {
        if (a.length < end) {
            throw;
        }
        if (start < 0) {
            throw;
        }

        n = new bytes(end-start);
        for ( uint i = start; i < end; i ++) { //python style slice
            n[i-start] = a[i];
        }
    }

    function () { throw; }
}


Revert unnmerged commits

Revert unnmerged commits

pragma solidity ^0.4.11;

import "./CanReclaimToken.sol";

/**
 * @title Contracts that should not own Tokens
 * @author Remco Bloemen <remco@2π.com>
 * @dev This blocks incoming ERC23 tokens to prevent accidental loss of tokens.
 * Should tokens (any ERC20Basic compatible) end up in the contract, it allows the
 * owner to reclaim the tokens.
 */
contract HasNoTokens is CanReclaimToken {

 /**
  * @dev Reject all ERC23 compatible tokens
  * @param from_ address The address that is transferring the tokens
  * @param value_ uint256 the amount of the specified token
  * @param data_ Bytes The data passed from the caller.
  */
  function tokenFallback(address from_, uint256 value_, bytes data_) external {
    revert();
  }

}

pragma solidity ^0.4.11;

import "./CanReclaimToken.sol";

/**
 * @title Contracts that should not own Tokens
 * @author Remco Bloemen <remco@2π.com>
 * @dev This blocks incoming ERC23 tokens to prevent accidental loss of tokens.
 * Should tokens (any ERC20Basic compatible) end up in the contract, it allows the
 * owner to reclaim the tokens.
 */
contract HasNoTokens is CanReclaimToken {

 /**
  * @dev Reject all ERC23 compatible tokens
  * param from_ address The address that is transferring the tokens
  * param value_ uint256 the amount of the specified token
  * param data_ Bytes The data passed from the caller.
  */
  function tokenFallback(address /*from_*/, uint256 /*value_*/, bytes /*data_*/) external {
    revert();
  }

}


small refactoring

small refactoring

contract MicropaymentsChannel {
    enum Stage {
        Empty,
        PartiallyConfirmed,
        Confirmed,
        Closing,
        Closed
    }

    uint public constant closingBlockDelay = 10;

    Stage public stage;
    uint public id;
    address public from;
    uint public fromBalance;
    address public to;
    uint public toBalance;
    uint public balanceTimestamp;

    uint public closingBlockNumber;

    function MicropaymentsChannel(address _from, address _to, uint _id) {
        stage = Stage.Empty;
        id  = _id;
        from = _from;
        fromBalance = 0;
        to = _to;
        toBalance = 0;
        balanceTimestamp = 0;
    }

    modifier onlyFrom {
        if (msg.sender != from) {
            throw;
        }
        _
    }

   modifier onlyTo {
        if (msg.sender != to) {
            throw;
        }
        _
    }

    modifier onlyParticipants {
        if ((msg.sender != from) && (msg.sender != to)) {
            throw;
        }
        _
    }

    modifier atStage(Stage _stage) {
        if (stage != _stage) {
            throw;
        }
        _
    }

    modifier atOneOfStages(Stage _stage1, Stage _stage2) {
        if ((stage != _stage1) && (stage != _stage2)) {
            throw;
        }
        _
    }

    modifier readyToClose() {
        if (block.number < closingBlockNumber) {
            throw;
        }
        _
    }

    function assertYoungerBalance(uint _balanceTimestamp) internal {
        if (_balanceTimestamp <= balanceTimestamp) {
            throw;
        }
    }

    function assertSaneBalance(uint _fromBalance, uint _toBalance) internal {
        if (fromBalance + toBalance < _fromBalance + _toBalance) {
            throw;
        }
    }

    function assertMessageHash(bytes32 _expected, bytes32 _sigHash) internal {
        if (_expected != _sigHash) {
            throw;
        }
    }

    function assertSignedByBoth(
        bytes32 _sigHash,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS
    ) internal {
        address signer = getSigner(_sigHash, _sigV, _sigR, _sigS);
        if (!(((from == msg.sender) && (to == signer)) ||
              ((from == signer) && (to == msg.sender)))) {
            throw;
        }
    }

    function getUpdateHash(
        uint _balanceTimestamp,
        uint _fromBalance,
        uint _toBalance
    ) constant returns(bytes32) {
        return sha3(id, _balanceTimestamp, _fromBalance, _toBalance);
    }

    function getSigner(
        bytes32 _sigHash,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS
    ) constant returns(address) {
        return ecrecover(_sigHash, _sigV, _sigR, _sigS);
    }

    function openChannel()
        onlyFrom
        atStage(Stage.Empty)
    {
        stage = Stage.PartiallyConfirmed;
        fromBalance = msg.value;
    }

    function confirmChannel()
        onlyTo
        atStage(Stage.PartiallyConfirmed)
    {
        stage = Stage.Confirmed;
        toBalance = msg.value;
    }

    function requestClosingChannel()
        onlyParticipants
        atOneOfStages(Stage.PartiallyConfirmed, Stage.Confirmed)
    {
        if (stage == Stage.PartiallyConfirmed) {
            suicide(from);
        } else {
            stage = Stage.Closing;
            closingBlockNumber = block.number + closingBlockDelay;
        }
    }

    function closeChannel()
        onlyParticipants
        atStage(Stage.Closing)
        readyToClose
    {
        stage = Stage.Closed;
        from.send(fromBalance);
        suicide(to);
    }

    function updateChannelState(
        uint _balanceTimestamp,
        uint _fromBalance,
        uint _toBalance,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS
    )
        onlyParticipants
        atOneOfStages(Stage.Confirmed, Stage.Closing)
    {
        assertYoungerBalance(_balanceTimestamp);
        assertSaneBalance(_fromBalance, _toBalance);
        assertSignedByBoth(getUpdateHash(_balanceTimestamp, _fromBalance, _toBalance), _sigV, _sigR, _sigS);
        balanceTimestamp = _balanceTimestamp;
        fromBalance = _fromBalance;
        toBalance = _toBalance;
    }
}

contract MicropaymentsChannel {
    enum Stage {
        Empty,
        PartiallyConfirmed,
        Confirmed,
        Closing,
        Closed
    }

    uint public constant closingBlockDelay = 10;

    Stage public stage;
    uint public id;
    address public from;
    uint public fromBalance;
    address public to;
    uint public toBalance;
    uint public balanceTimestamp;

    uint public closingBlockNumber;

    function MicropaymentsChannel(address _from, address _to, uint _id) {
        stage = Stage.Empty;
        id  = _id;
        from = _from;
        fromBalance = 0;
        to = _to;
        toBalance = 0;
        balanceTimestamp = 0;
    }

    modifier onlyFrom {
        if (msg.sender != from) {
            throw;
        }
        _
    }

   modifier onlyTo {
        if (msg.sender != to) {
            throw;
        }
        _
    }

    modifier onlyParticipants {
        if ((msg.sender != from) && (msg.sender != to)) {
            throw;
        }
        _
    }

    modifier atStage(Stage _stage) {
        if (stage != _stage) {
            throw;
        }
        _
    }

    modifier atOneOfStages(Stage _stage1, Stage _stage2) {
        if ((stage != _stage1) && (stage != _stage2)) {
            throw;
        }
        _
    }

    modifier readyToClose() {
        if (block.number < closingBlockNumber) {
            throw;
        }
        _
    }

    function assertYoungerBalance(uint _balanceTimestamp) internal {
        if (_balanceTimestamp <= balanceTimestamp) {
            throw;
        }
    }

    function assertSaneBalance(uint _fromBalance, uint _toBalance) internal {
        if (fromBalance + toBalance < _fromBalance + _toBalance) {
            throw;
        }
    }

    function assertMessageHash(bytes32 _expected, bytes32 _sigHash) internal {
        if (_expected != _sigHash) {
            throw;
        }
    }

    function assertSignedByBoth(
        bytes32 _sigHash,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS
    ) internal {
        address receiver = ecrecover(_sigHash, _sigV, _sigR, _sigS);
        if (!(((from == msg.sender) && (to == receiver)) ||
              ((from == receiver) && (to == msg.sender)))) {
            throw;
        }
    }

    function getUpdateHash(
        uint _balanceTimestamp,
        uint _fromBalance,
        uint _toBalance
    ) constant returns(bytes32) {
        return sha3(id, _balanceTimestamp, _fromBalance, _toBalance);
    }

    function getSigner(
        bytes32 _sigHash,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS
    ) constant returns(address) {
        return ecrecover(_sigHash, _sigV, _sigR, _sigS);
    }

    function openChannel()
        onlyFrom
        atStage(Stage.Empty)
    {
        stage = Stage.PartiallyConfirmed;
        fromBalance = msg.value;
    }

    function confirmChannel()
        onlyTo
        atStage(Stage.PartiallyConfirmed)
    {
        stage = Stage.Confirmed;
        toBalance = msg.value;
    }

    function requestClosingChannel()
        onlyParticipants
        atOneOfStages(Stage.PartiallyConfirmed, Stage.Confirmed)
    {
        if (stage == Stage.PartiallyConfirmed) {
            suicide(from);
        } else {
            stage = Stage.Closing;
            closingBlockNumber = block.number + closingBlockDelay;
        }
    }

    function closeChannel()
        onlyParticipants
        atStage(Stage.Closing)
        readyToClose
    {
        stage = Stage.Closed;
        from.send(fromBalance);
        suicide(to);
    }

    function updateChannelState(
        uint _balanceTimestamp,
        uint _fromBalance,
        uint _toBalance,
        uint8 _sigV,
        bytes32 _sigR,
        bytes32 _sigS
    )
        onlyParticipants
        atOneOfStages(Stage.Confirmed, Stage.Closing)
    {
        assertYoungerBalance(_balanceTimestamp);
        assertSaneBalance(_fromBalance, _toBalance);
        assertSignedByBoth(getUpdateHash(_balanceTimestamp, _fromBalance, _toBalance), _sigV, _sigR, _sigS);
        balanceTimestamp = _balanceTimestamp;
        fromBalance = _fromBalance;
        toBalance = _toBalance;
    }
}


Detail out comment on SequenceArray contract

/*
 * This is a third-party implementation of a SequenceArray, extracted into
 * a separate contract from Eris's `hello-eris` example repository.
 * SOURCE: https://github.com/eris-ltd/hello-eris/blob/master/contracts/DealManager.sol
 */

contract SequenceArray {
    // main map
    mapping(bytes32 => AddressElement) map;
    // separate list of known keys
    bytes32[] keys;
    uint mapSize;

    struct AddressElement {
        uint keyIdx;
        address value;
    }

    /**
     * @notice Inserts the given address value at the specified key.
     *
     * @param key the key
     * @param value the value
     * @return true, if the entry already existed and was replaced, false if a new entry was created
     */
    function insert(bytes32 key, address value) returns (bool exists)
    {
        exists = map[key].value != 0x0;
        if (!exists) {
            var keyIndex = keys.length++;
            keys[keyIndex] = key;
            map[key] = AddressElement(keyIndex, value);
            mapSize++;
        } else {
            // overwrite previous value
            map[key].value = value;
        }
    }

    /**
     * @return true if the map contains a value at the specified key, false otherwise.
     */
    function exists(bytes32 key) constant returns (bool exists) {
        return map[key].value != 0x0;
    }

    /**
     * @return the key at the given index or 0 if the index is out of bounds
     */
    function keyAtIndex(uint index) constant returns (bytes32 key) {
        if(index >= 0 && index < keys.length) {
            return keys[index];
        }
        return 0;
    }

    /**
      * @notice Returns the key at the given index position and the index of the next
      * artifact, if there is one, or 0 otherwise.
      * This method can be used as an iterator: As long as a nextIndex > 0 is returned, there
      * is another key.
    */
    function keyAtIndexHasNext(uint idx) public constant returns (bytes32 key, uint nextIndex) {
        nextIndex = 0;
        key = 0;
        if (idx >= 0 && idx < keys.length) {
            key = keys[idx];
            if (++idx < keys.length) {
                nextIndex = idx;
            }
        }
        return (key, nextIndex);
    }

    /**
      * @notice Returns the value at the given index position and the index of the next
      * artifact, if there is one, or 0 otherwise.
      * This method can be used as an iterator: As long as a nextIndex > 0 is returned, there
      * is another value.
    */
    function valueAtIndexHasNext(uint idx) public constant returns (address addr, uint nextIndex) {
        nextIndex = 0;
        addr = 0x0;
        if (idx >= 0 && idx < keys.length) {
            addr = value(keys[idx]);
            if (++idx < keys.length) {
                nextIndex = idx;
            }
        }
        return (addr, nextIndex);
    }

    /**
     * @return the index of the given key or -1 if the key does not exist
     */
    function keyIndex(bytes32 key) constant returns (int index) {
        var elem = map[key];
        if(elem.value == 0x0){
            return -1;
        }
        return int(elem.keyIdx);
    }

    /**
     * @return the size of the mapping, i.e. the number of currently stored entries
     */
    function size() constant returns (uint) {
        return mapSize;
    }

     /**
      * @return the address value registered at the specified key
      */
    function value(bytes32 key) constant returns (address addr) {
        if(map[key].value != 0x0) {
            return map[key].value;
        }
        else return 0x0;
    }
}

/*
 * This is a third-party implementation of a SequenceArray.
 * SOURCE: https://github.com/eris-ltd/hello-eris/blob/master/contracts/DealManager.sol
 */

contract SequenceArray {
    // main map
    mapping(bytes32 => AddressElement) map;
    // separate list of known keys
    bytes32[] keys;
    uint mapSize;

    struct AddressElement {
        uint keyIdx;
        address value;
    }

    /**
     * @notice Inserts the given address value at the specified key.
     *
     * @param key the key
     * @param value the value
     * @return true, if the entry already existed and was replaced, false if a new entry was created
     */
    function insert(bytes32 key, address value) returns (bool exists)
    {
        exists = map[key].value != 0x0;
        if (!exists) {
            var keyIndex = keys.length++;
            keys[keyIndex] = key;
            map[key] = AddressElement(keyIndex, value);
            mapSize++;
        } else {
            // overwrite previous value
            map[key].value = value;
        }
    }

    /**
     * @return true if the map contains a value at the specified key, false otherwise.
     */
    function exists(bytes32 key) constant returns (bool exists) {
        return map[key].value != 0x0;
    }

    /**
     * @return the key at the given index or 0 if the index is out of bounds
     */
    function keyAtIndex(uint index) constant returns (bytes32 key) {
        if(index >= 0 && index < keys.length) {
            return keys[index];
        }
        return 0;
    }

    /**
      * @notice Returns the key at the given index position and the index of the next
      * artifact, if there is one, or 0 otherwise.
      * This method can be used as an iterator: As long as a nextIndex > 0 is returned, there
      * is another key.
    */
    function keyAtIndexHasNext(uint idx) public constant returns (bytes32 key, uint nextIndex) {
        nextIndex = 0;
        key = 0;
        if (idx >= 0 && idx < keys.length) {
            key = keys[idx];
            if (++idx < keys.length) {
                nextIndex = idx;
            }
        }
        return (key, nextIndex);
    }

    /**
      * @notice Returns the value at the given index position and the index of the next
      * artifact, if there is one, or 0 otherwise.
      * This method can be used as an iterator: As long as a nextIndex > 0 is returned, there
      * is another value.
    */
    function valueAtIndexHasNext(uint idx) public constant returns (address addr, uint nextIndex) {
        nextIndex = 0;
        addr = 0x0;
        if (idx >= 0 && idx < keys.length) {
            addr = value(keys[idx]);
            if (++idx < keys.length) {
                nextIndex = idx;
            }
        }
        return (addr, nextIndex);
    }

    /**
     * @return the index of the given key or -1 if the key does not exist
     */
    function keyIndex(bytes32 key) constant returns (int index) {
        var elem = map[key];
        if(elem.value == 0x0){
            return -1;
        }
        return int(elem.keyIdx);
    }

    /**
     * @return the size of the mapping, i.e. the number of currently stored entries
     */
    function size() constant returns (uint) {
        return mapSize;
    }

     /**
      * @return the address value registered at the specified key
      */
    function value(bytes32 key) constant returns (address addr) {
        if(map[key].value != 0x0) {
            return map[key].value;
        }
        else return 0x0;
    }
}


make sign check for individual terms_address_hash

pragma solidity ^0.4.11;

import './token.sol';

/// @title Dutch auction contract - distribution of tokens using an auction.
/// @author [..] credits to Stefan George - <stefan.george@consensys.net>
contract DutchAuction {
    /*
    Auction for the TKN Token.
    Usage of the contract implies agreement of the Terms & Conditions
        Link: http://xyz.eth/tc.pdf
        MD5: e18de70182a134687249aebe6656049c

    Only addresses which signed the contract are allowed to call `bid`
    Users needs to called below, to explicitly sign agreement with the terms:
    `DutchAuction.sign('e18de70182a134687249aebe6656049c')`
    */

    /*
     *  Storage
     */

    // Keep track of signing the Terms and Conditions
    mapping (address => bool) public terms_signed;
    bytes32 terms_hash = 'e18de70182a134687249aebe6656049c';

    ReserveToken public token;
    address public owner;

    // Price function parameters
    uint public price_factor;
    uint public price_const;

    // For calculating elapsed time for price
    uint public start_time;
    uint public end_time;
    uint public start_block;

    // Keep track of funds claimed after auction has ended
    uint public funds_claimed;

    // Total number of tokens that will be auctioned
    uint public tokens_auctioned;

    // Wei per TKN (Tei * multiplier)
    uint public final_price;

    mapping (address => uint) public bids;

    Stages public stage;

    // Terminology:
    // 1 token unit = Tei
    // 1 token = TKN = Tei * multiplier
    // multiplier set from token's number of decimals (i.e. 10**decimals)
    uint multiplier;

    // TODO - remove after testing
    uint rounding_error_tokens;

    /*
     *  Enums
     */
    enum Stages {
        AuctionDeployed,
        AuctionSetUp,
        AuctionStarted,
        AuctionEnded,
        TokensDistributed,
        TradingStarted
    }

    /*
     *  Modifiers
     */
    modifier atStage(Stages _stage) {
        require(stage == _stage);
        _;
    }

    modifier isOwner() {
        require(msg.sender == owner);
        _;
    }

    modifier signedTerms() {
        require(terms_signed[msg.sender]);
        _;
    }

    modifier isValidPayload() {
        require(msg.data.length == 4 || msg.data.length == 36);
        _;
    }

    /*
     *  Events
     */

    event Deployed(address indexed auction, uint indexed price_factor, uint indexed price_const);
    event Setup();
    event SettingsChanged(uint indexed price_factor, uint indexed price_const);
    event AuctionStarted(uint indexed start_time, uint indexed block_number);
    event TermsSigned(address indexed sender, bytes32 indexed _terms_hash);
    event BidSubmission(address indexed sender, uint amount, uint returned_amount, uint indexed missing_reserve);
    event ClaimedTokens(address indexed recipient, uint sent_amount, uint num);
    event AuctionEnded(uint indexed final_price);
    event TokensDistributed();
    event TradingStarted();

    /*
     *  Public functions
     */

    /// @dev Contract constructor function sets owner.
    /// @param _price_factor Auction price factor.
    /// @param _price_const Auction price divisor constant.
    function DutchAuction(
        uint _price_factor,
        uint _price_const)
        public
    {
        owner = msg.sender;
        stage = Stages.AuctionDeployed;
        Deployed(this, price_factor, price_const);
        changeSettings(_price_factor, _price_const);
    }

    /// @dev Setup function sets external contracts' addresses.
    /// @param _token Token address.
    function setup(address _token)
        public
        isOwner
        atStage(Stages.AuctionDeployed)
    {
        require(_token != 0x0);
        token = ReserveToken(_token);
        require(token.owner() == owner);

        // Get number of tokens to be auctioned from token auction balance
        tokens_auctioned = token.balanceOf(this);

        // Set number of tokens multiplier from token decimals
        multiplier = 10**uint(token.decimals());

        stage = Stages.AuctionSetUp;
        Setup();

        // Tei auctioned
        assert(tokens_auctioned > multiplier);
    }

    /// @dev Changes auction start price factor before auction is started.
    /// @param _price_factor Updated price factor.
    /// @param _price_const Updated price divisor constant.
    function changeSettings(
        uint _price_factor,
        uint _price_const)
        public
        isOwner
    {
        require(stage == Stages.AuctionDeployed || stage == Stages.AuctionSetUp);
        require(_price_factor > 0);
        require(_price_const > 0);

        price_factor = _price_factor;
        price_const = _price_const;
        SettingsChanged(price_factor, price_const);
    }

    /// @dev Starts auction and sets start_time.
    function startAuction()
        public
        isOwner
        atStage(Stages.AuctionSetUp)
    {
        stage = Stages.AuctionStarted;
        start_time = now;
        start_block = block.number;
        AuctionStarted(start_time, start_block);
    }

    /// --------------------------------- Auction Functions -------------------------------------------

    /// @dev Allows to sing the terms.
    /// valid param is sha3(terms_hash, msg.sender) to enforce individual agreement
    function sign(bytes32 terms_address_hash)
        public
        atStage(Stages.AuctionStarted)
    {
        require(sha3(terms_hash, msg.sender) == terms_address_hash); // check if the correct terms are signed
        terms_signed[msg.sender] = true; // register digital signature
        TermsSigned(msg.sender, _terms_hash);
    }

    /// @dev Allows to send a bid to the auction.
    function bid()
        public
        payable
        atStage(Stages.AuctionStarted)
    {
        bid(msg.sender);
    }

    /// @dev Allows to send a bid to the auction.
    /// @param receiver Bidder account address.
    function bid(address receiver)
        public
        payable
        isValidPayload
        signedTerms
        atStage(Stages.AuctionStarted)
    {
        require(receiver != 0x0);
        require(msg.value > 0);

        uint amount = msg.value;
        uint pre_receiver_funds = bids[receiver];

        // Missing reserve without the current bid amount
        uint maxWei = missingReserveToEndAuction(this.balance - amount);

        // Only invest maximum possible amount.
        if (amount > maxWei) {
            amount = maxWei;
            // Send change back to receiver address.
            // TODO add test for this
            receiver.transfer(msg.value - amount);
        }
        bids[receiver] += amount;
        BidSubmission(receiver, amount, msg.value - amount, maxWei);

        if (maxWei == amount) {
            // When maxWei is equal to the big amount the auction is ended and finalizeAuction is triggered.
            finalizeAuction();
        }

        assert(bids[receiver] == pre_receiver_funds + amount);
    }

    /// @dev Claims tokens for bidder after auction. To be used if tokens can be claimed by bidders, individually.
    function claimTokens()
        public
        atStage(Stages.AuctionEnded)
    {
        claimTokens(msg.sender);
    }

    /// @dev Claims tokens for bidder after auction.
    /// @param receiver Tokens will be assigned to this address if set.
    function claimTokens(address receiver)
        public
        isValidPayload
        atStage(Stages.AuctionEnded)
    {
        require(receiver != 0x0);
        require(bids[receiver] > 0);

        // Number of Tei = bidded_wei / wei_per_TKN * multiplier
        uint num = multiplier * bids[receiver] / final_price;

        // Update funds claimed with full bidded amount
        // rounding errors are included to not block the contract
        funds_claimed += bids[receiver];

        // Set receiver bid to 0 before assigning tokens
        bids[receiver] = 0;

        token.transfer(receiver, num);
        ClaimedTokens(receiver, num, token.balanceOf(receiver));

        terms_signed[msg.sender] = false; // free storage

        // Test for a correct claimed tokens calculation
        /* TODO remove this after testing */
        uint auction_unclaimed_tokens = token.balanceOf(this);

        uint unclaimed_tokens = (this.balance - funds_claimed) * multiplier / final_price;
        unclaimed_tokens += rounding_error_tokens;

        if(auction_unclaimed_tokens != unclaimed_tokens) {
            rounding_error_tokens += 1;
            unclaimed_tokens += 1;
        }
        assert(auction_unclaimed_tokens == unclaimed_tokens);
        /* End of removable test */

        if (funds_claimed == this.balance) {
            stage = Stages.TokensDistributed;
            TokensDistributed();
            transferReserveToToken();
        }

        assert(num == token.balanceOf(receiver));
        assert(bids[receiver] == 0);
    }

    /*
     *  Private functions
     */

    /// @dev Finalize auction and set the final token price.
    function finalizeAuction()
        private
        atStage(Stages.AuctionStarted)
    {
        final_price = calcTokenPrice();
        end_time = now;
        stage = Stages.AuctionEnded;
        AuctionEnded(final_price);

        assert(final_price > 0);
    }

    /// @dev Transfer auction balance to the token.
    function transferReserveToToken()
        private
        atStage(Stages.TokensDistributed)
    {
        uint pre_balance = this.balance;

        token.receiveReserve.value(this.balance)();
        stage = Stages.TradingStarted;
        TradingStarted();

        assert(this.balance == 0);
        assert(token.balance == pre_balance);
    }

    /// @dev Calculates the token price at the current timestamp during the auction; elapsed time = 0 before auction starts.
    /// @dev At AuctionDeployed the price is 1, because multiplier is 0
    /// @return Returns the token price - Wei per TKN.
    function calcTokenPrice()
        constant
        private
        returns (uint)
    {
        uint elapsed;
        if(stage == Stages.AuctionStarted) {
            elapsed = now - start_time;
        }
        return multiplier * price_factor / (elapsed + price_const) + 1;
    }

    /// --------------------------------- Price Functions -------------------------------------------

    /// @dev Calculates current token price.
    /// @return Returns num Wei per TKN (multiplier * Tei).
    function price()
        public
        constant
        returns (uint)
    {
        if (stage == Stages.AuctionEnded ||
            stage == Stages.TokensDistributed ||
            stage == Stages.TradingStarted)
        {
            return 0;
        }
        return calcTokenPrice();
    }

    /// @dev The missing reserve amount necessary to end the auction at the current price.
    /// @return Returns the missing reserve amount.
    function missingReserveToEndAuction()
        constant
        public
        returns (uint)
    {
        return missingReserveToEndAuction(this.balance);
    }

    /// @dev The missing reserve amount necessary to end the auction at the current price, for a provided reserve/balance.
    /// @param reserve Reserve amount - might be current balance or current balance without current bid value for bid().
    /// @return Returns the missing reserve amount.
    function missingReserveToEndAuction(uint reserve)
        constant
        public
        returns (uint)
    {
        uint reserve_at_price = tokens_auctioned * price() / multiplier;
        if(reserve_at_price < reserve) {
            return 0;
        }
        return reserve_at_price - reserve;
    }
}

pragma solidity ^0.4.11;

import './token.sol';

/// @title Dutch auction contract - distribution of tokens using an auction.
/// @author [..] credits to Stefan George - <stefan.george@consensys.net>
contract DutchAuction {
    /*
    Auction for the TKN Token.
    Usage of the contract implies agreement of the Terms & Conditions
        Link: http://xyz.eth/tc.pdf
        MD5: e18de70182a134687249aebe6656049c

    Only addresses which signed the contract are allowed to call `bid`
    Users needs to called below, to explicitly sign agreement with the terms:
    `DutchAuction.sign('e18de70182a134687249aebe6656049c')`
    */

    /*
     *  Storage
     */

    // Keep track of signing the Terms and Conditions
    mapping (address => bool) public terms_signed;
    bytes32 terms_hash = 'e18de70182a134687249aebe6656049c';

    ReserveToken public token;
    address public owner;

    // Price function parameters
    uint public price_factor;
    uint public price_const;

    // For calculating elapsed time for price
    uint public start_time;
    uint public end_time;
    uint public start_block;

    // Keep track of funds claimed after auction has ended
    uint public funds_claimed;

    // Total number of tokens that will be auctioned
    uint public tokens_auctioned;

    // Wei per TKN (Tei * multiplier)
    uint public final_price;

    mapping (address => uint) public bids;

    Stages public stage;

    // Terminology:
    // 1 token unit = Tei
    // 1 token = TKN = Tei * multiplier
    // multiplier set from token's number of decimals (i.e. 10**decimals)
    uint multiplier;

    // TODO - remove after testing
    uint rounding_error_tokens;

    /*
     *  Enums
     */
    enum Stages {
        AuctionDeployed,
        AuctionSetUp,
        AuctionStarted,
        AuctionEnded,
        TokensDistributed,
        TradingStarted
    }

    /*
     *  Modifiers
     */
    modifier atStage(Stages _stage) {
        require(stage == _stage);
        _;
    }

    modifier isOwner() {
        require(msg.sender == owner);
        _;
    }

    modifier signedTerms() {
        require(terms_signed[msg.sender]);
        _;
    }

    modifier isValidPayload() {
        require(msg.data.length == 4 || msg.data.length == 36);
        _;
    }

    /*
     *  Events
     */

    event Deployed(address indexed auction, uint indexed price_factor, uint indexed price_const);
    event Setup();
    event SettingsChanged(uint indexed price_factor, uint indexed price_const);
    event AuctionStarted(uint indexed start_time, uint indexed block_number);
    event TermsSigned(address indexed sender, bytes32 indexed _terms_hash);
    event BidSubmission(address indexed sender, uint amount, uint returned_amount, uint indexed missing_reserve);
    event ClaimedTokens(address indexed recipient, uint sent_amount, uint num);
    event AuctionEnded(uint indexed final_price);
    event TokensDistributed();
    event TradingStarted();

    /*
     *  Public functions
     */

    /// @dev Contract constructor function sets owner.
    /// @param _price_factor Auction price factor.
    /// @param _price_const Auction price divisor constant.
    function DutchAuction(
        uint _price_factor,
        uint _price_const)
        public
    {
        owner = msg.sender;
        stage = Stages.AuctionDeployed;
        Deployed(this, price_factor, price_const);
        changeSettings(_price_factor, _price_const);
    }

    /// @dev Setup function sets external contracts' addresses.
    /// @param _token Token address.
    function setup(address _token)
        public
        isOwner
        atStage(Stages.AuctionDeployed)
    {
        require(_token != 0x0);
        token = ReserveToken(_token);
        require(token.owner() == owner);

        // Get number of tokens to be auctioned from token auction balance
        tokens_auctioned = token.balanceOf(this);

        // Set number of tokens multiplier from token decimals
        multiplier = 10**uint(token.decimals());

        stage = Stages.AuctionSetUp;
        Setup();

        // Tei auctioned
        assert(tokens_auctioned > multiplier);
    }

    /// @dev Changes auction start price factor before auction is started.
    /// @param _price_factor Updated price factor.
    /// @param _price_const Updated price divisor constant.
    function changeSettings(
        uint _price_factor,
        uint _price_const)
        public
        isOwner
    {
        require(stage == Stages.AuctionDeployed || stage == Stages.AuctionSetUp);
        require(_price_factor > 0);
        require(_price_const > 0);

        price_factor = _price_factor;
        price_const = _price_const;
        SettingsChanged(price_factor, price_const);
    }

    /// @dev Starts auction and sets start_time.
    function startAuction()
        public
        isOwner
        atStage(Stages.AuctionSetUp)
    {
        stage = Stages.AuctionStarted;
        start_time = now;
        start_block = block.number;
        AuctionStarted(start_time, start_block);
    }

    /// --------------------------------- Auction Functions -------------------------------------------

    /// @dev Allows to sing the terms.
    function sign(bytes32 _terms_hash)
        public
        atStage(Stages.AuctionStarted)
    {
        require(_terms_hash == terms_hash); // check if the correct terms are signed
        terms_signed[msg.sender]; // register digital signature
        TermsSigned(msg.sender, _terms_hash);
    }

    /// @dev Allows to send a bid to the auction.
    function bid()
        public
        payable
        atStage(Stages.AuctionStarted)
    {
        bid(msg.sender);
    }

    /// @dev Allows to send a bid to the auction.
    /// @param receiver Bidder account address.
    function bid(address receiver)
        public
        payable
        isValidPayload
        signedTerms
        atStage(Stages.AuctionStarted)
    {
        require(receiver != 0x0);
        require(msg.value > 0);

        uint amount = msg.value;
        uint pre_receiver_funds = bids[receiver];

        // Missing reserve without the current bid amount
        uint maxWei = missingReserveToEndAuction(this.balance - amount);

        // Only invest maximum possible amount.
        if (amount > maxWei) {
            amount = maxWei;
            // Send change back to receiver address.
            // TODO add test for this
            receiver.transfer(msg.value - amount);
        }
        bids[receiver] += amount;
        BidSubmission(receiver, amount, msg.value - amount, maxWei);

        if (maxWei == amount) {
            // When maxWei is equal to the big amount the auction is ended and finalizeAuction is triggered.
            finalizeAuction();
        }

        assert(bids[receiver] == pre_receiver_funds + amount);
    }

    /// @dev Claims tokens for bidder after auction. To be used if tokens can be claimed by bidders, individually.
    function claimTokens()
        public
        atStage(Stages.AuctionEnded)
    {
        claimTokens(msg.sender);
    }

    /// @dev Claims tokens for bidder after auction.
    /// @param receiver Tokens will be assigned to this address if set.
    function claimTokens(address receiver)
        public
        isValidPayload
        atStage(Stages.AuctionEnded)
    {
        require(receiver != 0x0);
        require(bids[receiver] > 0);

        // Number of Tei = bidded_wei / wei_per_TKN * multiplier
        uint num = multiplier * bids[receiver] / final_price;

        // Update funds claimed with full bidded amount
        // rounding errors are included to not block the contract
        funds_claimed += bids[receiver];

        // Set receiver bid to 0 before assigning tokens
        bids[receiver] = 0;

        token.transfer(receiver, num);
        ClaimedTokens(receiver, num, token.balanceOf(receiver));

        // Test for a correct claimed tokens calculation
        /* TODO remove this after testing */
        uint auction_unclaimed_tokens = token.balanceOf(this);

        uint unclaimed_tokens = (this.balance - funds_claimed) * multiplier / final_price;
        unclaimed_tokens += rounding_error_tokens;

        if(auction_unclaimed_tokens != unclaimed_tokens) {
            rounding_error_tokens += 1;
            unclaimed_tokens += 1;
        }
        assert(auction_unclaimed_tokens == unclaimed_tokens);
        /* End of removable test */

        if (funds_claimed == this.balance) {
            stage = Stages.TokensDistributed;
            TokensDistributed();
            transferReserveToToken();
        }

        assert(num == token.balanceOf(receiver));
        assert(bids[receiver] == 0);
    }

    /*
     *  Private functions
     */

    /// @dev Finalize auction and set the final token price.
    function finalizeAuction()
        private
        atStage(Stages.AuctionStarted)
    {
        final_price = calcTokenPrice();
        end_time = now;
        stage = Stages.AuctionEnded;
        AuctionEnded(final_price);

        assert(final_price > 0);
    }

    /// @dev Transfer auction balance to the token.
    function transferReserveToToken()
        private
        atStage(Stages.TokensDistributed)
    {
        uint pre_balance = this.balance;

        token.receiveReserve.value(this.balance)();
        stage = Stages.TradingStarted;
        TradingStarted();

        assert(this.balance == 0);
        assert(token.balance == pre_balance);
    }

    /// @dev Calculates the token price at the current timestamp during the auction; elapsed time = 0 before auction starts.
    /// @dev At AuctionDeployed the price is 1, because multiplier is 0
    /// @return Returns the token price - Wei per TKN.
    function calcTokenPrice()
        constant
        private
        returns (uint)
    {
        uint elapsed;
        if(stage == Stages.AuctionStarted) {
            elapsed = now - start_time;
        }
        return multiplier * price_factor / (elapsed + price_const) + 1;
    }

    /// --------------------------------- Price Functions -------------------------------------------

    /// @dev Calculates current token price.
    /// @return Returns num Wei per TKN (multiplier * Tei).
    function price()
        public
        constant
        returns (uint)
    {
        if (stage == Stages.AuctionEnded ||
            stage == Stages.TokensDistributed ||
            stage == Stages.TradingStarted)
        {
            return 0;
        }
        return calcTokenPrice();
    }

    /// @dev The missing reserve amount necessary to end the auction at the current price.
    /// @return Returns the missing reserve amount.
    function missingReserveToEndAuction()
        constant
        public
        returns (uint)
    {
        return missingReserveToEndAuction(this.balance);
    }

    /// @dev The missing reserve amount necessary to end the auction at the current price, for a provided reserve/balance.
    /// @param reserve Reserve amount - might be current balance or current balance without current bid value for bid().
    /// @return Returns the missing reserve amount.
    function missingReserveToEndAuction(uint reserve)
        constant
        public
        returns (uint)
    {
        uint reserve_at_price = tokens_auctioned * price() / multiplier;
        if(reserve_at_price < reserve) {
            return 0;
        }
        return reserve_at_price - reserve;
    }
}


Change std/Token to an abstract contract

contract Token {
	event Transfer(address indexed _from, address indexed _to, uint256 _value);
	event Approval(address indexed _owner, address indexed _spender, uint256 _value);

	function totalSupply() constant returns (uint256 supply);
	function balanceOf(address _owner) constant returns (uint256 balance);
	function transfer(address _to, uint256 _value) returns (bool success);
	function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
	function approve(address _spender, uint256 _value) returns (bool success);
	function allowance(address _owner, address _spender) constant returns (uint256 remaining);
}

contract Token {
	event Transfer(address indexed _from, address indexed _to, uint256 _value);
	event Approval(address indexed _owner, address indexed _spender, uint256 _value);

	function totalSupply() constant returns (uint256 supply) {}
	function balanceOf(address _owner) constant returns (uint256 balance) {}
	function transfer(address _to, uint256 _value) returns (bool success) {}
	function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {}
	function approve(address _spender, uint256 _value) returns (bool success) {}
	function allowance(address _owner, address _spender) constant returns (uint256 remaining) {}
}