Fix forgotten ; in Chess.sol

Fix forgotten ; in Chess.sol

/**
 * Chess contract
 * Stores any amount of games with two players and current state.
 * State encoding:
 *    positive numbers for white, negative numbers for black
 *    for details, see
 *    https://github.com/ise-ethereum/on-chain-chess/wiki/Chess-board-representation
 */

import "TurnBasedGame.sol";
import "ChessLogic.sol";
import "Auth.sol";

contract Chess is TurnBasedGame, Auth {
    using ChessLogic for ChessLogic.State;
    mapping (bytes32 => ChessLogic.State) gameStates;

    event GameInitialized(bytes32 indexed gameId, address indexed player1, string player1Alias, address playerWhite, uint pot);
    event GameJoined(bytes32 indexed gameId, address indexed player1, string player1Alias, address indexed player2, string player2Alias, address playerWhite, uint pot);
    event GameStateChanged(bytes32 indexed gameId, int8[128] state);
    event GameTimeoutStarted(bytes32 indexed gameId,uint timeoutStarted, int8 timeoutState);
    event Move(bytes32 indexed gameId, address indexed player, uint256 fromIndex, uint256 toIndex);

    function Chess(bool enableDebugging) TurnBasedGame(enableDebugging) {
    }

    /**
     * Initialize a new game
     * string player1Alias: Alias of the player creating the game
     * bool playAsWhite: Pass true or false depending on if the creator will play as white
     */
    function initGame(string player1Alias, bool playAsWhite) public returns (bytes32) {
        bytes32 gameId = super.initGame(player1Alias, playAsWhite);

        // Setup game state
        int8 nextPlayerColor = int8(1);
        gameStates[gameId].setupState(nextPlayerColor);
        if (playAsWhite) {
            // Player 1 will play as white
            gameStates[gameId].playerWhite = msg.sender;

            // Game starts with White, so here player 1
            games[gameId].nextPlayer = games[gameId].player1;
        }

        // Sent notification events
        GameInitialized(gameId, games[gameId].player1, player1Alias, gameStates[gameId].playerWhite, games[gameId].pot);
        GameStateChanged(gameId, gameStates[gameId].fields);
        return gameId;
    }

    /**
     * Join an initialized game
     * bytes32 gameId: ID of the game to join
     * string player2Alias: Alias of the player that is joining
     */
    function joinGame(bytes32 gameId, string player2Alias) public {
        super.joinGame(gameId, player2Alias);

        // If the other player isn't white, player2 will play as white
        if (gameStates[gameId].playerWhite == 0) {
            gameStates[gameId].playerWhite = msg.sender;
            // Game starts with White, so here player2
            games[gameId].nextPlayer = games[gameId].player2;
        }

        GameJoined(gameId, games[gameId].player1, games[gameId].player1Alias, games[gameId].player2, player2Alias, gameStates[gameId].playerWhite, games[gameId].pot);
    }

    /**
    *
    * verify signature of state
    * verify signature of move
    * apply state, verify move
    */
    function moveFromState(bytes32 gameId, int8[128] state, uint256 fromIndex, uint256 toIndex,
                           bytes sigState, bytes sigFromIndex, bytes sigToIndex) notEnded(gameId) public {

        if (games[gameId].winner != 0 || games[gameId].ended) {
            // Game already ended
            throw;
        }

        // check whether sender is a member of this game
        if (games[gameId].player1 != msg.sender && games[gameId].player2 != msg.sender) {
            throw;
        }

        // find opponent to msg.sender
        address opponent;
        if (games[gameId].player1 != msg.sender) {
            opponent = games[gameId].player1;
        } else {
            opponent = games[gameId].player1;
        }

        /*
        * Verify signatures and that mover is current player
        */

        // verify fromIndex and figure out who wants to move
        address mover;
        if (verifySig(msg.sender, sha3(fromIndex), sigFromIndex)) {
            mover = msg.sender;
        } else if (verifySig(opponent, sha3(fromIndex), sigFromIndex)) {
            mover = opponent;
        } else {
            throw;
        }

        // check whether mover is currentPlayer in state
        int8 playerColor = mover == gameStates[gameId].playerWhite ? int8(1) : int8(-1);

        //if (state[ChessLogic.Flags(ChessLogic.Flag.CURRENT_PLAYER)] !=  playerColor) {
        if (state[56] !=  playerColor) {
            throw;
        }

        // verify toIndex
        if (!verifySig(mover, sha3(toIndex), sigToIndex)) {
            throw;
        }

        // verify state - should be signed by the other member of game - not mover
        if (mover == msg.sender && !verifySig(opponent, sha3(state), sigState)) {
            throw;
        } else if (mover == opponent && !verifySig(msg.sender, sha3(state), sigState)) {
            throw;
        }

        // check move count. New state should have a higher move count.
        if ((state[8] * int8(128) + state[9]) < (gameStates[gameId].fields[8] * int8(128) + gameStates[gameId].fields[9])) {
            throw;
        }

        // apply state
        gameStates[gameId].setState(state, playerColor);
        games[gameId].nextPlayer =  mover;

        // apply and verify move
        move(gameId, fromIndex, toIndex);
    }

    function move(bytes32 gameId, uint256 fromIndex, uint256 toIndex) notEnded(gameId) public {
        if (games[gameId].nextPlayer != msg.sender) {
            throw;
        }
        if(games[gameId].timeoutState != 0) {
            games[gameId].timeoutState = 0;
        }
        // Chess move validation
        gameStates[gameId].move(fromIndex, toIndex);

        // Set nextPlayer
        if (msg.sender == games[gameId].player1) {
            games[gameId].nextPlayer = games[gameId].player2;
        } else {
            games[gameId].nextPlayer = games[gameId].player1;
        }

        // Send events
        Move(gameId, msg.sender, fromIndex, toIndex);
        GameStateChanged(gameId, gameStates[gameId].fields);
    }

    /* Explicit set game state. Only in debug mode */
    function setGameState(bytes32 gameId, int8[128] state, address nextPlayer) debugOnly public {
        int8 playerColor = nextPlayer == gameStates[gameId].playerWhite ? int8(1) : int8(-1);
        gameStates[gameId].setState(state, playerColor);
        games[gameId].nextPlayer = nextPlayer;
        GameStateChanged(gameId, gameStates[gameId].fields);
    }

    function getCurrentGameState(bytes32 gameId) constant returns (int8[128]) {
       return gameStates[gameId].fields;
    }

    function getWhitePlayer(bytes32 gameId) constant returns (address) {
       return gameStates[gameId].playerWhite;
    }

    /* The sender claims he has won the game. Starts a timeout. */
    function claimWin(bytes32 gameId) notEnded(gameId) public {

        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout has not started
        if (game.timeoutState != 0)
            throw;
        // you can only claim draw / victory in the enemies turn
        if (msg.sender == game.nextPlayer)
            throw;
        // get the color of the player that wants to claim win
        int8 requestingPlayerColor = 0;
        // the one not sending is white -> the sending player is Black

        if(gameStates[gameId].playerWhite == msg.sender){

            // this like causes : Module build failed: Error: Internal compiler error: I sense a disturbance in the stack.
            // Why no clue, bad choice to set the value explicitly, if the enum changes this line breaks
            requestingPlayerColor = -1;
        // else he is white

        }else{
            // same here
            requestingPlayerColor = 1;
        }

        // We get the king position of that player
        uint256 kingIndex = uint256(gameStates[gameId].getOwnKing(requestingPlayerColor));
        // if he is in check the request is legal
        if (gameStates[gameId].checkForCheck(kingIndex, requestingPlayerColor)){
            game.timeoutStarted = now;
            game.timeoutState = 1;
            GameTimeoutStarted(gameId, game.timeoutStarted, game.timeoutState);
        // else it is not
        }else {
            throw;
        }

    }

    /* The sender offers the other player a draw. Starts a timeout. */
    function offerDraw(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout has not started
        if (game.timeoutState != 0)
            throw;
        // you can only claim draw / victory in the enemies turn
        if (msg.sender == game.nextPlayer)
            throw;
        game.timeoutStarted = now;
        game.timeoutState = -1;

        GameTimeoutStarted(gameId,game.timeoutStarted,game.timeoutState);
    }

    /* the sender claims that the other player is not in the game anymore. Starts a Timeout that can be claimed*/
    function claimTimeout(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout has not started
        if (game.timeoutState != 0)
            throw;
        // you can only claim draw / victory in the enemies turn
        if (msg.sender == game.nextPlayer)
            throw;
        game.timeoutStarted = now;
        game.timeoutState = 1;
        GameTimeoutStarted(gameId, game.timeoutStarted, game.timeoutState);
    }
    /* The sender claims a previously started timeout. */
    function claimTimeoutEnded(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        if (msg.sender == game.nextPlayer)
            throw;
        if (game.timeoutState == 0)
            throw;
        if (now < game.timeoutStarted + 10 minutes)
            throw;
        // Game is a draw, transfer ether back
        if (game.timeoutState == -1){
            game.ended = true;
            games[gameId].player1Winnings = games[gameId].pot / 2;
            games[gameId].player2Winnings = games[gameId].pot / 2;
            games[gameId].pot = 0;
            GameEnded(gameId);
        } else if (game.timeoutState == 1){
            game.ended = true;
            game.winner = msg.sender;
            if(msg.sender == game.player1) {
                games[gameId].player1Winnings = games[gameId].pot;
                games[gameId].pot = 0;
            }
            else {
                games[gameId].player2Winnings = games[gameId].pot;
                games[gameId].pot = 0;
            }

            GameEnded(gameId);
        } else {
            throw;
        }
    }

    /* A timeout can be confirmed by the non-initializing player. */
    function confirmGameEnded(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        if (msg.sender != game.nextPlayer)
            throw;
        if (game.timeoutState == 0)
            throw;
        // Game is a draw, transfer ether back
        if (game.timeoutState == -1){
            game.ended = true;
            games[gameId].player1Winnings = games[gameId].pot / 2;
            games[gameId].player2Winnings = games[gameId].pot / 2;
            games[gameId].pot = 0;
            GameEnded(gameId);
        } else if (game.timeoutState == 1){
            game.ended = true;
            // other player won
            if(msg.sender == game.player1) {
                game.winner = game.player2;
                games[gameId].player2Winnings = games[gameId].pot;
                games[gameId].pot = 0;
            }
            else {
                game.winner = game.player1;
                games[gameId].player1Winnings = games[gameId].pot;
                games[gameId].pot = 0;
            }
            GameEnded(gameId);
        } else {
            throw;
        }
    }

    /* This unnamed function is called whenever someone tries to send ether to the contract */
    function () {
        throw; // Prevents accidental sending of ether
    }
}

/**
 * Chess contract
 * Stores any amount of games with two players and current state.
 * State encoding:
 *    positive numbers for white, negative numbers for black
 *    for details, see
 *    https://github.com/ise-ethereum/on-chain-chess/wiki/Chess-board-representation
 */

import "TurnBasedGame.sol";
import "ChessLogic.sol";
import "Auth.sol";

contract Chess is TurnBasedGame, Auth {
    using ChessLogic for ChessLogic.State;
    mapping (bytes32 => ChessLogic.State) gameStates;

    event GameInitialized(bytes32 indexed gameId, address indexed player1, string player1Alias, address playerWhite, uint pot);
    event GameJoined(bytes32 indexed gameId, address indexed player1, string player1Alias, address indexed player2, string player2Alias, address playerWhite, uint pot);
    event GameStateChanged(bytes32 indexed gameId, int8[128] state);
    event GameTimeoutStarted(bytes32 indexed gameId,uint timeoutStarted, int8 timeoutState);
    event Move(bytes32 indexed gameId, address indexed player, uint256 fromIndex, uint256 toIndex);

    function Chess(bool enableDebugging) TurnBasedGame(enableDebugging) {
    }

    /**
     * Initialize a new game
     * string player1Alias: Alias of the player creating the game
     * bool playAsWhite: Pass true or false depending on if the creator will play as white
     */
    function initGame(string player1Alias, bool playAsWhite) public returns (bytes32) {
        bytes32 gameId = super.initGame(player1Alias, playAsWhite);

        // Setup game state
        int8 nextPlayerColor = int8(1);
        gameStates[gameId].setupState(nextPlayerColor);
        if (playAsWhite) {
            // Player 1 will play as white
            gameStates[gameId].playerWhite = msg.sender;

            // Game starts with White, so here player 1
            games[gameId].nextPlayer = games[gameId].player1;
        }

        // Sent notification events
        GameInitialized(gameId, games[gameId].player1, player1Alias, gameStates[gameId].playerWhite, games[gameId].pot);
        GameStateChanged(gameId, gameStates[gameId].fields);
        return gameId;
    }

    /**
     * Join an initialized game
     * bytes32 gameId: ID of the game to join
     * string player2Alias: Alias of the player that is joining
     */
    function joinGame(bytes32 gameId, string player2Alias) public {
        super.joinGame(gameId, player2Alias);

        // If the other player isn't white, player2 will play as white
        if (gameStates[gameId].playerWhite == 0) {
            gameStates[gameId].playerWhite = msg.sender;
            // Game starts with White, so here player2
            games[gameId].nextPlayer = games[gameId].player2;
        }

        GameJoined(gameId, games[gameId].player1, games[gameId].player1Alias, games[gameId].player2, player2Alias, gameStates[gameId].playerWhite, games[gameId].pot);
    }

    /**
    *
    * verify signature of state
    * verify signature of move
    * apply state, verify move
    */
    function moveFromState(bytes32 gameId, int8[128] state, uint256 fromIndex, uint256 toIndex,
                           bytes sigState, bytes sigFromIndex, bytes sigToIndex) notEnded(gameId) public {

        if (games[gameId].winner != 0 || games[gameId].ended) {
            // Game already ended
            throw;
        }

        // check whether sender is a member of this game
        if (games[gameId].player1 != msg.sender && games[gameId].player2 != msg.sender) {
            throw;
        }

        // find opponent to msg.sender
        address opponent;
        if (games[gameId].player1 != msg.sender) {
            opponent = games[gameId].player1
        } else {
            opponent = games[gameId].player1
        }

        /*
        * Verify signatures and that mover is current player
        */

        // verify fromIndex and figure out who wants to move
        address mover;
        if (verifySig(msg.sender, sha3(fromIndex), sigFromIndex)) {
            mover = msg.sender;
        } else if (verifySig(opponent, sha3(fromIndex), sigFromIndex)) {
            mover = opponent;
        } else {
            throw;
        }

        // check whether mover is currentPlayer in state
        int8 playerColor = mover == gameStates[gameId].playerWhite ? int8(1) : int8(-1);

        //if (state[ChessLogic.Flags(ChessLogic.Flag.CURRENT_PLAYER)] !=  playerColor) {
        if (state[56] !=  playerColor) {
            throw;
        }

        // verify toIndex
        if (!verifySig(mover, sha3(toIndex), sigToIndex)) {
            throw;
        }

        // verify state - should be signed by the other member of game - not mover
        if (mover == msg.sender && !verifySig(opponent, sha3(state), sigState)) {
            throw;
        } else if (mover == opponent && !verifySig(msg.sender, sha3(state), sigState)) {
            throw;
        }

        // check move count. New state should have a higher move count.
        if ((state[8] * int8(128) + state[9]) < (gameStates[gameId].fields[8] * int8(128) + gameStates[gameId].fields[9])) {
            throw;
        }

        // apply state
        gameStates[gameId].setState(state, playerColor);
        games[gameId].nextPlayer =  mover;

        // apply and verify move
        move(gameId, fromIndex, toIndex);
    }

    function move(bytes32 gameId, uint256 fromIndex, uint256 toIndex) notEnded(gameId) public {
        if (games[gameId].nextPlayer != msg.sender) {
            throw;
        }
        if(games[gameId].timeoutState != 0) {
            games[gameId].timeoutState = 0;
        }
        // Chess move validation
        gameStates[gameId].move(fromIndex, toIndex);

        // Set nextPlayer
        if (msg.sender == games[gameId].player1) {
            games[gameId].nextPlayer = games[gameId].player2;
        } else {
            games[gameId].nextPlayer = games[gameId].player1;
        }

        // Send events
        Move(gameId, msg.sender, fromIndex, toIndex);
        GameStateChanged(gameId, gameStates[gameId].fields);
    }

    /* Explicit set game state. Only in debug mode */
    function setGameState(bytes32 gameId, int8[128] state, address nextPlayer) debugOnly public {
        int8 playerColor = nextPlayer == gameStates[gameId].playerWhite ? int8(1) : int8(-1);
        gameStates[gameId].setState(state, playerColor);
        games[gameId].nextPlayer = nextPlayer;
        GameStateChanged(gameId, gameStates[gameId].fields);
    }

    function getCurrentGameState(bytes32 gameId) constant returns (int8[128]) {
       return gameStates[gameId].fields;
    }

    function getWhitePlayer(bytes32 gameId) constant returns (address) {
       return gameStates[gameId].playerWhite;
    }

    /* The sender claims he has won the game. Starts a timeout. */
    function claimWin(bytes32 gameId) notEnded(gameId) public {

        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout has not started
        if (game.timeoutState != 0)
            throw;
        // you can only claim draw / victory in the enemies turn
        if (msg.sender == game.nextPlayer)
            throw;
        // get the color of the player that wants to claim win
        int8 requestingPlayerColor = 0;
        // the one not sending is white -> the sending player is Black

        if(gameStates[gameId].playerWhite == msg.sender){

            // this like causes : Module build failed: Error: Internal compiler error: I sense a disturbance in the stack.
            // Why no clue, bad choice to set the value explicitly, if the enum changes this line breaks
            requestingPlayerColor = -1;
        // else he is white

        }else{
            // same here
            requestingPlayerColor = 1;
        }

        // We get the king position of that player
        uint256 kingIndex = uint256(gameStates[gameId].getOwnKing(requestingPlayerColor));
        // if he is in check the request is legal
        if (gameStates[gameId].checkForCheck(kingIndex, requestingPlayerColor)){
            game.timeoutStarted = now;
            game.timeoutState = 1;
            GameTimeoutStarted(gameId, game.timeoutStarted, game.timeoutState);
        // else it is not
        }else {
            throw;
        }

    }

    /* The sender offers the other player a draw. Starts a timeout. */
    function offerDraw(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout has not started
        if (game.timeoutState != 0)
            throw;
        // you can only claim draw / victory in the enemies turn
        if (msg.sender == game.nextPlayer)
            throw;
        game.timeoutStarted = now;
        game.timeoutState = -1;

        GameTimeoutStarted(gameId,game.timeoutStarted,game.timeoutState);
    }

    /* the sender claims that the other player is not in the game anymore. Starts a Timeout that can be claimed*/
    function claimTimeout(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        // only if timeout has not started
        if (game.timeoutState != 0)
            throw;
        // you can only claim draw / victory in the enemies turn
        if (msg.sender == game.nextPlayer)
            throw;
        game.timeoutStarted = now;
        game.timeoutState = 1;
        GameTimeoutStarted(gameId, game.timeoutStarted, game.timeoutState);
    }
    /* The sender claims a previously started timeout. */
    function claimTimeoutEnded(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        if (msg.sender == game.nextPlayer)
            throw;
        if (game.timeoutState == 0)
            throw;
        if (now < game.timeoutStarted + 10 minutes)
            throw;
        // Game is a draw, transfer ether back
        if (game.timeoutState == -1){
            game.ended = true;
            games[gameId].player1Winnings = games[gameId].pot / 2;
            games[gameId].player2Winnings = games[gameId].pot / 2;
            games[gameId].pot = 0;
            GameEnded(gameId);
        } else if (game.timeoutState == 1){
            game.ended = true;
            game.winner = msg.sender;
            if(msg.sender == game.player1) {
                games[gameId].player1Winnings = games[gameId].pot;
                games[gameId].pot = 0;
            }
            else {
                games[gameId].player2Winnings = games[gameId].pot;
                games[gameId].pot = 0;
            }

            GameEnded(gameId);
        } else {
            throw;
        }
    }

    /* A timeout can be confirmed by the non-initializing player. */
    function confirmGameEnded(bytes32 gameId) notEnded(gameId) public {
        var game = games[gameId];
        // just the two players currently playing
        if (msg.sender != game.player1 && msg.sender != game.player2)
            throw;
        if (msg.sender != game.nextPlayer)
            throw;
        if (game.timeoutState == 0)
            throw;
        // Game is a draw, transfer ether back
        if (game.timeoutState == -1){
            game.ended = true;
            games[gameId].player1Winnings = games[gameId].pot / 2;
            games[gameId].player2Winnings = games[gameId].pot / 2;
            games[gameId].pot = 0;
            GameEnded(gameId);
        } else if (game.timeoutState == 1){
            game.ended = true;
            // other player won
            if(msg.sender == game.player1) {
                game.winner = game.player2;
                games[gameId].player2Winnings = games[gameId].pot;
                games[gameId].pot = 0;
            }
            else {
                game.winner = game.player1;
                games[gameId].player1Winnings = games[gameId].pot;
                games[gameId].pot = 0;
            }
            GameEnded(gameId);
        } else {
            throw;
        }
    }

    /* This unnamed function is called whenever someone tries to send ether to the contract */
    function () {
        throw; // Prevents accidental sending of ether
    }
}


Data type changes to reduce gas deployment costs

pragma solidity ^0.4.11;

contract Dgp {

    struct Client {
        uint startTime;
        uint lastRedemptionBlock;
        uint32 checkingBalance;
        uint32 depositedEndowments;
        uint32 endowmentTotal;
    }
    struct Vendor {
        uint8 registered;
        uint32 balance;
    }
    address public superAdmin;
    address public admin;
    uint32 public accountBalance;
    uint public allocated;
    uint32 public constant redemptionFrequency = 7; //7 days
    uint32 public constant redemptionAmt = 7000; //DUST (in cents)
    uint public minClientBalance =    3000000000000000; //wei .003 ETH use 2500000000000000 for testing due to truffle gas bug
    uint public clientGasAddAmt =  15000000000000000; //wei .015 ETH PRODUCTION
    // uint public minClientBalance =   97000000000000000; //wei .0970 ETH use 2500000000000000 for testing due to truffle gas bug
    // uint public clientGasAddAmt =    100000000000000000; //wei .1 ETH TESTING due to truffle gas bug, just enough for 2 tx's causing a top off before 3rd

    mapping (address => Vendor) public vendors;
    mapping (address => Client) public clients;
    mapping (address => uint) public supporters;

    // events
    event USDDonation(uint32 _value);
    event UnlockedDeposit(address indexed _to, uint32 _value);
    event LockedDeposit(address indexed _to, uint32 _value);
    event RemoveClient(address indexed _removed, uint32 _value);
    event Purchase(address indexed _client, address indexed _vendor, uint32 _value);
    event Refund(address indexed _vendor, address _client, uint32 _value);
    event Redemption(address indexed _vendor, uint32 _value);
    event PurchaseDonation(address indexed _vendor, uint32 _value);
    event SupporterETHDonation(address indexed _supporter, uint _value);
    event RunningOutOfGas(address indexed _client);
    event Transfer(address _recipient, uint _value);

    //access control
    modifier onlySuperAdmin {
		if (msg.sender != superAdmin)  revert();
		_;
	}
	modifier onlyAdmin {
		if (msg.sender != admin)  revert();
		_;
	}

    modifier onlySuperOrAdmin {
		if ((msg.sender != admin) && (msg.sender != superAdmin))  revert();
		_;
	}

	modifier onlyClient {
		if (clients[msg.sender].startTime == 0)  revert();
		_;
	}
	modifier onlyVendorWithBalance {
		if (vendors[msg.sender].balance == 0)  revert();
		_;
	}

        // constructor
    function Dgp(address _admin)
    {
      superAdmin = msg.sender;
      admin = _admin;
    }
    function registerDonation(uint32 _donationAmt) onlyAdmin() {
        accountBalance += _donationAmt;
        USDDonation(_donationAmt);
    }

    function registerClient(address _clientAddress, uint32 _endowmentAmt, uint _startTime) onlyAdmin() {
        //never allocate more than account balance
        if (_endowmentAmt <= 0) revert();
        if (_endowmentAmt + allocated > accountBalance) revert();
        if (clients[_clientAddress].endowmentTotal > 0) revert();
        //TODO use safeAdd?
        allocated += _endowmentAmt;
        clients[_clientAddress].checkingBalance = 0;
        clients[_clientAddress].endowmentTotal = _endowmentAmt;
        clients[_clientAddress].startTime = _startTime == 0 ? now : _startTime;
        clients[_clientAddress].lastRedemptionBlock = 0;
        checkClientFunds(_clientAddress);
        if (_endowmentAmt > 0) LockedDeposit(_clientAddress, _endowmentAmt);

    }
    function checkClientFunds(address _clientAddress) internal {
        if ((_clientAddress.balance < minClientBalance) && (this.balance > clientGasAddAmt)) {
            _clientAddress.transfer(clientGasAddAmt);
        }
        else
        {
          RunningOutOfGas(_clientAddress);
        }
    }
    function registerVendor(address _vendorAddress) onlyAdmin() {
        vendors[_vendorAddress].registered = 1;
    }

    //Used by admin to give immediately vested DUST to client
    function depositChecking(address _clientAddress, uint32 _amount) onlyAdmin() external {
        if (clients[_clientAddress].endowmentTotal == 0) revert();
        if (allocated + _amount > accountBalance) revert();
        allocated += _amount;
        clients[_clientAddress].checkingBalance += _amount;
        UnlockedDeposit(_clientAddress, _amount);
    }
    function depositSavings(address _clientAddress, uint32 _amount) onlyAdmin() external {
        if (clients[_clientAddress].endowmentTotal == 0) revert();
        if (allocated + _amount > accountBalance) revert();
        allocated += _amount;
        clients[_clientAddress].endowmentTotal += _amount;
        LockedDeposit(_clientAddress, _amount);
    }
    function removeClient(address _clientAddress) onlyAdmin() external {
        if (clients[_clientAddress].endowmentTotal == 0) revert();
        uint32 clientFunds = clients[_clientAddress].checkingBalance +
         clients[_clientAddress].endowmentTotal - clients[_clientAddress].depositedEndowments;

        allocated -= clientFunds;
        RemoveClient(_clientAddress, clientFunds);
        delete clients[_clientAddress];
    }
    function getVested(address _clientAddress) constant returns(uint32 vested) {
        if (clients[_clientAddress].endowmentTotal == 0) revert();
        uint endowmentDuration = (now - clients[_clientAddress].startTime);
        uint32 earnedEndowments = uint32(endowmentDuration / (redemptionFrequency * 1 days));
        return (earnedEndowments * redemptionAmt - clients[_clientAddress].depositedEndowments);
    }
    function getCheckingBalance(address _clientAddress) constant external returns(uint32 checkingBalance) {
        if (clients[_clientAddress].endowmentTotal == 0) revert();
        checkingBalance = getVested(_clientAddress) + clients[_clientAddress].checkingBalance;
    }

    //Returns a virtual savings account balance, i.e. that which has been endowed but that can't be spent, maybe call it TrustBalance?
    function getSavingsBalance(address _clientAddress) constant external returns(uint32 savingsBalance) {
        if (clients[_clientAddress].endowmentTotal == 0) revert();
        savingsBalance = clients[_clientAddress].endowmentTotal -
        getVested(_clientAddress) - clients[_clientAddress].depositedEndowments;
    }

    function makePurchase(address _vendorAddress, uint32 amount) onlyClient() external  {
        if (vendors[_vendorAddress].registered == 0) revert(); //vendor check
        uint32 vested = getVested(msg.sender);
        if (vested + clients[msg.sender].checkingBalance < amount) revert();
        clients[msg.sender].depositedEndowments += vested;
        clients[msg.sender].checkingBalance += vested-amount;
        vendors[_vendorAddress].balance += amount;
        checkClientFunds(msg.sender);
        Purchase(msg.sender, _vendorAddress, amount);
    }
    function refundClient(address _clientAddress, uint32 amount) onlyVendorWithBalance() external {
        if (clients[_clientAddress].endowmentTotal == 0) revert(); //client addr check
        if (vendors[msg.sender].balance < amount) revert();
        clients[_clientAddress].checkingBalance += amount;
        Refund(msg.sender,_clientAddress,amount);
    }

    function makePurchaseForClient(address _vendorAddress, address _clientAddress, uint32 amount)
       onlyAdmin() external {
        if (vendors[_vendorAddress].registered == 0) revert(); //vendor check
        uint32 vested = getVested(_clientAddress);
        if (vested + clients[_clientAddress].checkingBalance < amount) revert();
        clients[_clientAddress].depositedEndowments += vested;
        clients[_clientAddress].checkingBalance += vested-amount;
        vendors[_vendorAddress].balance += amount;
        Purchase(_clientAddress, _vendorAddress, amount);
    }

    function redeemPurchases() onlyVendorWithBalance() external {
        uint32 balance = vendors[msg.sender].balance;
        vendors[msg.sender].balance = 0;
        accountBalance -= balance;
        allocated -= balance;
        Redemption(msg.sender,balance);
    }
    function donatePurchase(uint32 _amount) onlyVendorWithBalance() external {
        uint32 balance = vendors[msg.sender].balance;
        if (_amount > balance) revert();
        accountBalance -= _amount;
        allocated -= _amount;
        PurchaseDonation(msg.sender,_amount);
    }
    function redeemPurchasesForVendor(address _vendorAddress) onlyAdmin() external {
        if (vendors[_vendorAddress].registered == 0) revert(); //vendor check
        uint32 balance = vendors[_vendorAddress].balance;
        vendors[_vendorAddress].balance = 0;
        accountBalance -= balance;
        allocated -= balance;
        Redemption(_vendorAddress,balance);
    }
    function transferETH(address _recipient, uint amount) onlySuperAdmin() external {
       if (this.balance < amount) revert();
       _recipient.transfer(amount);

    }
    function terminate() onlySuperAdmin external {
        selfdestruct(superAdmin);
    }
    function () payable {
        if(msg.value == 0) revert();
        supporters[msg.sender] += msg.value;
        SupporterETHDonation(msg.sender,msg.value);
    }
}

pragma solidity ^0.4.11;

contract Dgp {

    struct Client {
        uint256 startTime;
        uint256 lastRedemptionBlock;
        uint256 checkingBalance;
        uint256 depositedEndowments;
        uint256 endowmentTotal;
    }
    struct Vendor {
        uint8 registered;
        uint256 balance;
    }
    address public superAdmin;
    address public admin;
    uint256 public accountBalance;
    uint256 public allocated;
    uint256 public constant redemptionFrequency = 7; //7 days
    uint256 public constant redemptionAmt = 7000; //DUST (in cents)
    //uint256 public minClientBalance =    3000000000000000; //wei .003 ETH use 2500000000000000 for testing due to truffle gas bug
    // uint256 public clientGasAddAmt =  15000000000000000; //wei .015 ETH PRODUCTION
    uint256 public minClientBalance =   97000000000000000; //wei .0970 ETH use 2500000000000000 for testing due to truffle gas bug
    uint256 public clientGasAddAmt =    100000000000000000; //wei .1 ETH TESTING due to truffle gas bug, just enough for 2 tx's causing a top off before 3rd

    mapping (address => Vendor) public vendors;
    mapping (address => Client) public clients;
    mapping (address => uint256) public supporters;

    // events
    event USDDonation(uint256 _value);
    event UnlockedDeposit(address indexed _to, uint256 _value);
    event LockedDeposit(address indexed _to, uint256 _value);
    event RemoveClient(address indexed _removed, uint256 _value);
    event Purchase(address indexed _client, address indexed _vendor, uint256 _value);
    event Refund(address indexed _vendor, address _client, uint256 _value);
    event Redemption(address indexed _vendor, uint256 _value);
    event SupporterETHDonation(address indexed _supporter, uint256 _value);
    event RunningOutOfGas(address indexed _client);
    event Transfer(address _recipient, uint256 _value);

    //access control
    modifier onlySuperAdmin {
		if (msg.sender != superAdmin)  revert();
		_;
	}
	modifier onlyAdmin {
		if (msg.sender != admin)  revert();
		_;
	}

    modifier onlySuperOrAdmin {
		if ((msg.sender != admin) && (msg.sender != superAdmin))  revert();
		_;
	}

	modifier onlyClient {
		if (clients[msg.sender].startTime == 0)  revert();
		_;
	}
	modifier onlyVendorWithBalance {
		if (vendors[msg.sender].balance == 0)  revert();
		_;
	}

        // constructor
    function Dgp(address _admin)
    {
      superAdmin = msg.sender;
      admin = _admin;
    }
    function registerDonation(uint256 _donationAmt) onlyAdmin() {
        accountBalance += _donationAmt;
        USDDonation(_donationAmt);
    }

    function registerClient(address _clientAddress, uint256 _endowmentAmt, uint256 _startTime) onlyAdmin() {
        //never allocate more than account balance
        if (_endowmentAmt <= 0) revert();
        if (_endowmentAmt + allocated > accountBalance) revert();
        if (clients[_clientAddress].endowmentTotal > 0) revert();
        //TODO use safeAdd?
        allocated += _endowmentAmt;
        clients[_clientAddress].checkingBalance = 0;
        clients[_clientAddress].endowmentTotal = _endowmentAmt;
        clients[_clientAddress].startTime = _startTime == 0 ? now : _startTime;
        clients[_clientAddress].lastRedemptionBlock = 0;
        checkClientFunds(_clientAddress);
        if (_endowmentAmt > 0) LockedDeposit(_clientAddress, _endowmentAmt);

    }
    function checkClientFunds(address _clientAddress) internal {
        if ((_clientAddress.balance < minClientBalance) && (this.balance > clientGasAddAmt)) {
            _clientAddress.transfer(clientGasAddAmt);
        }
        else
        {
          RunningOutOfGas(_clientAddress);
        }
    }
    function registerVendor(address _vendorAddress) onlyAdmin() {
        vendors[_vendorAddress].registered = 1;
    }

    //Used by admin to give immediately vested DUST to client
    function depositChecking(address _clientAddress, uint256 _amount) onlyAdmin() external {
        if (clients[_clientAddress].endowmentTotal == 0) revert();
        if (allocated + _amount > accountBalance) revert();
        allocated += _amount;
        clients[_clientAddress].checkingBalance += _amount;
        UnlockedDeposit(_clientAddress, _amount);
    }
    function depositSavings(address _clientAddress, uint256 _amount) onlyAdmin() external {
        if (clients[_clientAddress].endowmentTotal == 0) revert();
        if (allocated + _amount > accountBalance) revert();
        allocated += _amount;
        clients[_clientAddress].endowmentTotal += _amount;
        LockedDeposit(_clientAddress, _amount);
    }
    function removeClient(address _clientAddress) onlyAdmin() external {
        if (clients[_clientAddress].endowmentTotal == 0) revert();
        uint256 clientFunds = clients[_clientAddress].checkingBalance +
         clients[_clientAddress].endowmentTotal - clients[_clientAddress].depositedEndowments;

        allocated -= clientFunds;
        RemoveClient(_clientAddress, clientFunds);
        delete clients[_clientAddress];
    }
    function getVested(address _clientAddress) constant returns(uint256 vested) {
        if (clients[_clientAddress].endowmentTotal == 0) revert();
        uint256 endowmentDuration = (now - clients[_clientAddress].startTime);
        uint256 earnedEndowments = endowmentDuration / (redemptionFrequency * 1 days);
        return (earnedEndowments * redemptionAmt - clients[_clientAddress].depositedEndowments);
    }
    function getCheckingBalance(address _clientAddress) constant external returns(uint256 checkingBalance) {
        if (clients[_clientAddress].endowmentTotal == 0) revert();
        checkingBalance = getVested(_clientAddress) + clients[_clientAddress].checkingBalance;
    }

    //Returns a virtual savings account balance, i.e. that which has been endowed but that can't be spent, maybe call it TrustBalance?
    function getSavingsBalance(address _clientAddress) constant external returns(uint256 savingsBalance) {
        if (clients[_clientAddress].endowmentTotal == 0) revert();
        savingsBalance = clients[_clientAddress].endowmentTotal -
        getVested(_clientAddress) - clients[_clientAddress].depositedEndowments;
    }

    function makePurchase(address _vendorAddress, uint256 amount) onlyClient() external  {
        if (vendors[_vendorAddress].registered == 0) revert(); //vendor check
        uint256 vested = getVested(msg.sender);
        if (vested + clients[msg.sender].checkingBalance < amount) revert();
        clients[msg.sender].depositedEndowments += vested;
        clients[msg.sender].checkingBalance += vested-amount;
        vendors[_vendorAddress].balance += amount;
        checkClientFunds(msg.sender);
        Purchase(msg.sender, _vendorAddress, amount);
    }
    function refundClient(address _clientAddress, uint256 amount) onlyVendorWithBalance() external {
        if (clients[_clientAddress].endowmentTotal == 0) revert(); //client addr check
        if (vendors[msg.sender].balance < amount) revert();
        clients[_clientAddress].checkingBalance += amount;
        Refund(msg.sender,_clientAddress,amount);
    }

    function makePurchaseForClient(address _vendorAddress, address _clientAddress, uint256 amount)
       onlyAdmin() external {
        if (vendors[_vendorAddress].registered == 0) revert(); //vendor check
        uint256 vested = getVested(_clientAddress);
        if (vested + clients[_clientAddress].checkingBalance < amount) revert();
        clients[_clientAddress].depositedEndowments += vested;
        clients[_clientAddress].checkingBalance += vested-amount;
        vendors[_vendorAddress].balance += amount;
        Purchase(_clientAddress, _vendorAddress, amount);
    }

    function redeemPurchases() onlyVendorWithBalance() external {
        uint256 balance = vendors[msg.sender].balance;
        vendors[msg.sender].balance = 0;
        accountBalance -= balance;
        allocated -= balance;
        Redemption(msg.sender,balance);
    }

    function redeemPurchasesForVendor(address _vendorAddress) onlyAdmin() external {
        if (vendors[_vendorAddress].registered == 0) revert(); //vendor check
        uint256 balance = vendors[_vendorAddress].balance;
        vendors[_vendorAddress].balance = 0;
        accountBalance -= balance;
        allocated -= balance;
        Redemption(_vendorAddress,balance);
    }
    function transferETH(address _recipient, uint256 amount) onlySuperAdmin() external {
       if (this.balance < amount) revert();
       _recipient.transfer(amount);

    }
    function terminate() onlySuperAdmin external {
        selfdestruct(superAdmin);
    }
    function () payable {
        if(msg.value == 0) revert();
        supporters[msg.sender] += msg.value;
        SupporterETHDonation(msg.sender,msg.value);
    }
}


Update WeiFund_Beta_Launch.sol

Update WeiFund_Beta_Launch.sol

// WeiFund v1.0
// Start, donate, payout and refund crowdfunding campaigns on Ethereum
// If campaign goal is not reached by the stated expiry, all funds are refundable back to oringial contributor accounts
// If campaign goal is reached or surpassed by stated expiry, all raised funds will be paid out to campaign beneficiary

/// @title The core WeiFund confirgutation hook interface
/// @author Nick Dodson <thenickdodson@gmail.com>
contract WeiFundConfig {
    function newCampaign(uint _campaignID, address _owner, uint _fundingGoal){}
    function contribute(uint _campaignID, address _contributor, uint _amountContributed){}
    function refund(uint _campaignID, address _contributor, uint _amountRefunded){}
    function payout(uint _campaignID, uint _amountRaised){}
}

/// @title The core WeiFund crowdfunding interface
/// @author Nick Dodson <thenickdodson@gmail.com>
contract WeiFundInterface {
    /// @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 _beneficiary The address of the beneficiary for this campaign
    /// @param _fundingGoal 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 _expiry When the campaign will expire and contributions can no longer be made
    /// @param _config The configuration address
    function newCampaign(string _name, address _beneficiary, uint _fundingGoal, uint _expiry, address _config) {}

    /// @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 _campaignID (Campaign ID) The ID number of the crowdfunding campaign
    /// @param _beneficiary (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 _campaignID, address _beneficiary) {}

    /// @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 _campaignID (Campaign ID) The ID number of the crowdfunding campaign to be refunded
    function refund(uint _campaignID) {}

    /// @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 _campaignID (Campaign ID) The ID number of the crowdfunding campaign
    function payout(uint _campaignID) {}

    /// @notice User Campaign ID (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 _user The address of the campaign operator.
    /// @param _userCampaignID The user campaign ID
    /// @return _campaignID The campaign ID
    function userCampaignID(address _user, uint _userCampaignID) constant returns (uint _campaignID) {}

    /// @notice Total Number of Campaigns Started for a Given User
    /// @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 _user The user's address
    /// @return _numCampaigns The number of campaigns
    function totalUserCampaigns(address _user) constant returns (uint _numCampaigns) {}

    /// @notice The total number of campaigns on WeiFund
    /// @dev This method returns the total number of campaigns on WeiFund as an unsigned integer
    /// @return _numCampaigns The number of campaigns
    function totalCampaigns() constant returns (uint _numCampaigns) {}

    /// @notice Contributor At ID;
    /// @dev For retrieving the contributor data at a specific contributor ID
    /// @param _campaignID The address of the campaign operator.
    /// @param _contributorID The user campaign ID
    /// @return _contributor, _beneficiary, _amountContributed, _refunded
    function contributorAt(uint _campaignID, uint _contributorID) constant returns (address _contributor,
                                                                                address _beneficiary,
                                                                                uint _amountContributed,
                                                                                bool _refunded){}
    function createdAt(uint _campaignID) public constant returns (uint){}
    function contributorID(uint _campaignID, address _contributorAddress) constant returns (uint) {}
    function ownerOf(uint _campaignID) constant returns (address){}
    function beneficiaryOf(uint _campaignID) constant returns (address){}
    function configOf(uint _campaignID) constant returns (address){}
    function amountRaisedBy(uint _campaignID) constant returns (uint){}
    function fundingGoalOf(uint _campaignID) constant returns (uint){}
    function expiryOf(uint _campaignID) constant returns (uint){}
    function totalContributors(uint _campaignID) constant returns (uint){}

    function isContributor(uint _campaignID, address _contributorAddress) constant returns (bool) {}
    function isOwner(uint _campaignID, address _owner) constant returns (bool){}
    function hasFailed(uint _campaignID) constant returns (bool){}
    function isSuccess(uint _campaignID) constant returns (bool){}
    function isPaidOut(uint _campaignID) constant returns (bool){}
    function totalRefunded(uint _campaignID) constant returns (uint){}
    function isRefunded(uint _campaignID) constant returns (bool){}

    event CampaignCreated(address indexed _owner, uint indexed _campaignID);
    event Contributed(address indexed _contributor, uint indexed _campaignID, uint _amountContributed);
    event PaidOut(address indexed _beneficiary, uint indexed _campaignID, uint _amountPaid);
    event Refunded(address indexed _contributor, uint indexed _campaignID, uint _amountRefunded);
}

/// @title WeiFund - A Decentralized Crowdfunding Platform
/// @author Nick Dodson <thenickdodson@gmail.com>
contract WeiFund is WeiFundInterface {
    // @notice User; A user is an account that has started campaigns on WeiFund
    // @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 Contributor; This object helps store the pertinant contributer data.
    // @dev This object stores the contributer data, such as the contributer address, and amount.
    struct Contributor {
        address addr;
        address beneficiary;
        uint amountContributed;
        bool refunded;
    }

    // @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 {
        string name;
        address owner;
        address beneficiary;
        address config;
        bool paidOut;
        uint expiry;
        uint fundingGoal;
        uint amountRaised;
        uint created;
        uint numContributors;
        mapping (uint => Contributor) contributors;
        mapping (address => uint) toContributor;
    }

    /// @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;

    function newCampaign(string _name, address _beneficiary, uint _fundingGoal, uint _expiry, address _config) public {
        if(_fundingGoal <= 0 || _expiry <= now)
            throw;

        uint _campaignID = numCampaigns++; // campaignID is return variable
        Campaign c = campaigns[_campaignID];  // assigns reference
        c.name = _name;
        c.owner = msg.sender;
        c.beneficiary = _beneficiary;
        c.fundingGoal = _fundingGoal;
        c.expiry = _expiry;
        c.created = now;
        c.config = _config;

        User u = users[msg.sender];
        uint u_campaignID = u.numCampaigns++;
        u.campaigns[u_campaignID] = _campaignID;

        CampaignCreated(msg.sender, _campaignID);

        if(c.config != address(0))
            WeiFundConfig(c.config).newCampaign(_campaignID, msg.sender, _fundingGoal);
    }

    function contribute(uint _campaignID, address _beneficiary) public {
        Campaign c = campaigns[_campaignID];

        if(now > c.expiry || msg.value == 0)
            throw;

        uint backerID = c.numContributors++;
        Contributor backer = c.contributors[backerID];
        backer.addr = msg.sender;
        backer.beneficiary = _beneficiary;
        backer.amountContributed = msg.value;
        c.amountRaised += backer.amountContributed;
        c.toContributor[msg.sender] = backerID;
        Contributed(msg.sender, _campaignID, c.amountRaised);

        if(c.config != address(0))
            WeiFundConfig(c.config).contribute(_campaignID, msg.sender, msg.value);
    }

    function refund(uint _campaignID) public {
        Campaign c = campaigns[_campaignID];

        if (!hasFailed(_campaignID))
            throw;

        Contributor backer = c.contributors[c.toContributor[msg.sender]];

        if(backer.amountContributed <= 0 || backer.refunded)
            throw;

        address receiver = backer.addr;

        if(backer.addr != address(0))
            receiver = backer.addr;

        receiver.send(backer.amountContributed);
        Refunded(receiver, _campaignID, backer.amountContributed);
        backer.refunded = true;

        if(c.config != address(0))
            WeiFundConfig(c.config).refund(_campaignID, receiver, backer.amountContributed);
    }

    function payout(uint _campaignID) public {
        Campaign c = campaigns[_campaignID];

        if(!isSuccess(_campaignID))
            throw;

        c.beneficiary.send(c.amountRaised);
        PaidOut(msg.sender, _campaignID, c.amountRaised);
        c.amountRaised = 0;
        c.paidOut = true;

        if(c.config != address(0))
            WeiFundConfig(c.config).payout(_campaignID, c.amountRaised);
    }

    function userCampaignID(address _user, uint _userCampaignID) public constant returns (uint _campaignID) {
        User u = users[_user];

        return u.campaigns[_userCampaignID];
    }

    function totalUserCampaigns(address _user) constant returns (uint _numCampaigns) {
        User u = users[_user];

        return u.numCampaigns;
    }

    function totalCampaigns() constant returns (uint _numCampaigns) {
        return numCampaigns;
    }

    function contributorAt(uint _campaignID, uint _contributorID) public constant returns (address _contributor,
                                                                                address _beneficiary,
                                                                                uint _amountContributed,
                                                                                bool _refunded) {
        Campaign c = campaigns[_campaignID];

        return (c.contributors[_contributorID].addr,
                c.contributors[_contributorID].beneficiary,
                c.contributors[_contributorID].amountContributed,
                c.contributors[_contributorID].refunded);
    }

    function contributorID(uint _campaignID, address _contributorAddress) public constant returns (uint) {
        Campaign c = campaigns[_campaignID];

        return c.toContributor[_contributorAddress];
    }

    function isContributor(uint _campaignID, address _contributorAddress) public constant returns (bool) {
        Campaign c = campaigns[_campaignID];

        if(c.contributors[c.toContributor[_contributorAddress]].amountContributed != 0)
            return true;
    }

    function ownerOf(uint _campaignID) public constant returns (address){
        Campaign c = campaigns[_campaignID];

        return c.owner;
    }

    function beneficiaryOf(uint _campaignID) public constant returns (address){
        Campaign c = campaigns[_campaignID];

        return c.beneficiary;
    }

    function configOf(uint _campaignID) public constant returns (address){
        Campaign c = campaigns[_campaignID];

        return c.config;
    }

    function amountRaisedBy(uint _campaignID) public constant returns (uint){
        Campaign c = campaigns[_campaignID];

        return c.amountRaised;
    }

    function fundingGoalOf(uint _campaignID) public constant returns (uint){
        Campaign c = campaigns[_campaignID];

        return c.fundingGoal;
    }

    function expiryOf(uint _campaignID) public constant returns (uint){
        Campaign c = campaigns[_campaignID];

        return c.expiry;
    }

    function createdAt(uint _campaignID) public constant returns (uint){
        Campaign c = campaigns[_campaignID];

        return c.created;
    }

    function totalContributors(uint _campaignID) public constant returns (uint){
        Campaign c = campaigns[_campaignID];

        return c.numContributors;
    }

    function isOwner(uint _campaignID, address _owner) public constant returns (bool){
        Campaign c = campaigns[_campaignID];

        if(c.owner == _owner)
            return true;
    }

    function hasFailed(uint _campaignID) public constant returns (bool){
        Campaign c = campaigns[_campaignID];

        if (now > c.expiry
            && c.amountRaised < c.fundingGoal
            && c.amountRaised > 0)
            return true;
    }

    function isSuccess(uint _campaignID) public constant returns (bool){
        Campaign c = campaigns[_campaignID];

        if (c.amountRaised >= c.fundingGoal)
            return true;
    }

    function isPaidOut(uint _campaignID) public constant returns (bool){
        Campaign c = campaigns[_campaignID];

        return c.paidOut;
    }

    function totalRefunded(uint _campaignID) public constant returns (uint){
        Campaign c = campaigns[_campaignID];
        uint refunded = 0;

        if(!hasFailed(_campaignID))
            return 0;

        for(uint contributorID = 0; contributorID < c.numContributors; contributorID++) {
            if(c.contributors[contributorID].refunded == true)
                refunded += c.contributors[contributorID].amountContributed;
        }

        return refunded;
    }

    function isRefunded(uint _campaignID) public constant returns (bool){
        Campaign c = campaigns[_campaignID];

        for(uint contributorID = 0; contributorID < c.numContributors; contributorID++) {
            if(c.contributors[contributorID].refunded != true)
                return false;
        }

        return true;
    }
}

// WeiFund v1.0
// Start, donate, payout and refund crowdfunding campaigns on Ethereum
// If campaign goal is not reached by the stated expiry, all funds are refundable back to oringial contributor accounts
// If campaign goal is reached or surpassed by stated expiry, all raised funds will be paid out to campaign beneficiary

/// @title The core WeiFund confirgutation hook interface
/// @author Nick Dodson <thenickdodson@gmail.com>
contract WeiFundConfig {
    function newCampaign(uint _campaignID, address _owner, uint _fundingGoal){}
    function contribute(uint _campaignID, address _contributorAddress, uint _amountContributed){}
    function refund(uint _campaignID, address _contributorAddress, uint _amountRefunded){}
    function payout(uint _campaignID, uint _amountRaised){}
}

/// @title The core WeiFund crowdfunding interface
/// @author Nick Dodson <thenickdodson@gmail.com>
contract WeiFundInterface {
    /// @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 _beneficiary The address of the beneficiary for this campaign
    /// @param _fundingGoal 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 _expiry When the campaign will expire and contributions can no longer be made
    /// @param _config The configuration address
    function newCampaign(string _name, address _beneficiary, uint _fundingGoal, uint _expiry, address _config) {}

    /// @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 _campaignID (Campaign ID) The ID number of the crowdfunding campaign
    /// @param _beneficiary (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 _campaignID, address _beneficiary) {}

    /// @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 _campaignID (Campaign ID) The ID number of the crowdfunding campaign to be refunded
    function refund(uint _campaignID) {}

    /// @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 _campaignID (Campaign ID) The ID number of the crowdfunding campaign
    function payout(uint _campaignID) {}

    /// @notice User Campaign ID (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 _userAddress The address of the campaign operator.
    /// @param _userCampaignID The user campaign ID
    /// @return _campaignID The campaign ID
    function userCampaignID(address _userAddress, uint _userCampaignID) constant returns (uint _campaignID) {}

    /// @notice Total Number of Campaigns Started for a Given User
    /// @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 _userAddress The user's address
    /// @return _numCampaigns The number of campaigns
    function totalUserCampaigns(address _userAddress) constant returns (uint _numCampaigns) {}

    /// @notice The total number of campaigns on WeiFund
    /// @dev This method returns the total number of campaigns on WeiFund as an unsigned integer
    /// @return _numCampaigns The number of campaigns
    function totalCampaigns() constant returns (uint _numCampaigns) {}

    /// @notice Contributor At ID;
    /// @dev For retrieving the contributor data at a specific contributor ID
    /// @param _campaignID The address of the campaign operator.
    /// @param _contributorID The user campaign ID
    /// @return _contributor, _beneficiary, _amountContributed, _refunded
    function contributorAt(uint _campaignID, uint _contributorID) constant returns (address _contributor,
                                                                                address _beneficiary,
                                                                                uint _amountContributed,
                                                                                bool _refunded){}
    function createdAt(uint _campaignID) public constant returns (uint){}
    function contributorID(uint _campaignID, address _contributorAddress) constant returns (uint) {}
    function ownerOf(uint _campaignID) constant returns (address){}
    function beneficiaryOf(uint _campaignID) constant returns (address){}
    function configOf(uint _campaignID) constant returns (address){}
    function amountRaisedBy(uint _campaignID) constant returns (uint){}
    function fundingGoalOf(uint _campaignID) constant returns (uint){}
    function expiryOf(uint _campaignID) constant returns (uint){}
    function totalContributors(uint _campaignID) constant returns (uint){}

    function isContributor(uint _campaignID, address _contributorAddress) constant returns (bool) {}
    function isOwner(uint _campaignID, address _owner) constant returns (bool){}
    function hasFailed(uint _campaignID) constant returns (bool){}
    function isSuccess(uint _campaignID) constant returns (bool){}
    function isPaidOut(uint _campaignID) constant returns (bool){}
    function totalRefunded(uint _campaignID) constant returns (uint){}
    function isRefunded(uint _campaignID) constant returns (bool){}

    event CampaignCreated(address indexed _owner, uint indexed _campaignID);
    event Contributed(address indexed _contributor, uint indexed _campaignID, uint _amountContributed);
    event PaidOut(address indexed _beneficiary, uint indexed _campaignID, uint _amountPaid);
    event Refunded(address indexed _contributor, uint indexed _campaignID, uint _amountRefunded);
}

/// @title WeiFund - A Decentralized Crowdfunding Platform
/// @author Nick Dodson <thenickdodson@gmail.com>
contract WeiFund is WeiFundInterface {
    // @notice User; A user is an account that has started campaigns on WeiFund
    // @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 Contributor; This object helps store the pertinant contributer data.
    // @dev This object stores the contributer data, such as the contributer address, and amount.
    struct Contributor {
        address addr;
        address beneficiary;
        uint amountContributed;
        bool refunded;
    }

    // @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 {
        string name;
        address owner;
        address beneficiary;
        address config;
        bool paidOut;
        uint expiry;
        uint fundingGoal;
        uint amountRaised;
        uint created;
        uint numContributors;
        mapping (uint => Contributor) contributors;
        mapping (address => uint) toContributor;
    }

    /// @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;

    function newCampaign(string _name, address _beneficiary, uint _fundingGoal, uint _expiry, address _config) public {
        if(_fundingGoal <= 0 || _expiry <= now)
            throw;

        uint _campaignID = numCampaigns++; // campaignID is return variable
        Campaign c = campaigns[_campaignID];  // assigns reference
        c.name = _name;
        c.owner = msg.sender;
        c.beneficiary = _beneficiary;
        c.fundingGoal = _fundingGoal;
        c.expiry = _expiry;
        c.created = now;
        c.config = _config;

        User u = users[msg.sender];
        uint u_campaignID = u.numCampaigns++;
        u.campaigns[u_campaignID] = _campaignID;

        CampaignCreated(msg.sender, _campaignID);

        if(c.config != address(0))
            WeiFundConfig(c.config).newCampaign(_campaignID, msg.sender, _fundingGoal);
    }

    function contribute(uint _campaignID, address _beneficiary) public {
        Campaign c = campaigns[_campaignID];

        if(now > c.expiry || msg.value == 0)
            throw;

        uint backerID = c.numContributors++;
        Contributor backer = c.contributors[backerID];
        backer.addr = msg.sender;
        backer.beneficiary = _beneficiary;
        backer.amountContributed = msg.value;
        c.amountRaised += backer.amountContributed;
        c.toContributor[msg.sender] = backerID;
        Contributed(msg.sender, _campaignID, c.amountRaised);

        if(c.config != address(0))
            WeiFundConfig(c.config).contribute(_campaignID, msg.sender, msg.value);
    }

    function refund(uint _campaignID) public {
        Campaign c = campaigns[_campaignID];

        if (!hasFailed(_campaignID))
            throw;

        Contributor backer = c.contributors[c.toContributor[msg.sender]];

        if(backer.amountContributed <= 0 || backer.refunded)
            throw;

        address receiver = backer.addr;

        if(backer.addr != address(0))
            receiver = backer.addr;

        receiver.send(backer.amountContributed);
        Refunded(receiver, _campaignID, backer.amountContributed);
        backer.refunded = true;

        if(c.config != address(0))
            WeiFundConfig(c.config).refund(_campaignID, receiver, backer.amountContributed);
    }

    function payout(uint _campaignID) public {
        Campaign c = campaigns[_campaignID];

        if(!isSuccess(_campaignID))
            throw;

        c.beneficiary.send(c.amountRaised);
        PaidOut(msg.sender, _campaignID, c.amountRaised);
        c.amountRaised = 0;
        c.paidOut = true;

        if(c.config != address(0))
            WeiFundConfig(c.config).payout(_campaignID, c.amountRaised);
    }

    function userCampaignID(address _userAddress, uint _userCampaignID) public constant returns (uint _campaignID) {
        User u = users[_userAddress];

        return u.campaigns[_userCampaignID];
    }

    function totalUserCampaigns(address _userAddress) constant returns (uint _numCampaigns) {
        User u = users[_userAddress];

        return u.numCampaigns;
    }

    function totalCampaigns() constant returns (uint _numCampaigns) {
        return numCampaigns;
    }

    function contributorAt(uint _campaignID, uint _contributorID) public constant returns (address _contributor,
                                                                                address _beneficiary,
                                                                                uint _amountContributed,
                                                                                bool _refunded) {
        Campaign c = campaigns[_campaignID];

        return (c.contributors[_contributorID].addr,
                c.contributors[_contributorID].beneficiary,
                c.contributors[_contributorID].amountContributed,
                c.contributors[_contributorID].refunded);
    }

    function contributorID(uint _campaignID, address _contributorAddress) public constant returns (uint) {
        Campaign c = campaigns[_campaignID];

        return c.toContributor[_contributorAddress];
    }

    function isContributor(uint _campaignID, address _contributorAddress) public constant returns (bool) {
        Campaign c = campaigns[_campaignID];

        if(c.contributors[c.toContributor[_contributorAddress]].amountContributed != 0)
            return true;
    }

    function ownerOf(uint _campaignID) public constant returns (address){
        Campaign c = campaigns[_campaignID];

        return c.owner;
    }

    function beneficiaryOf(uint _campaignID) public constant returns (address){
        Campaign c = campaigns[_campaignID];

        return c.beneficiary;
    }

    function configOf(uint _campaignID) public constant returns (address){
        Campaign c = campaigns[_campaignID];

        return c.config;
    }

    function amountRaisedBy(uint _campaignID) public constant returns (uint){
        Campaign c = campaigns[_campaignID];

        return c.amountRaised;
    }

    function fundingGoalOf(uint _campaignID) public constant returns (uint){
        Campaign c = campaigns[_campaignID];

        return c.fundingGoal;
    }

    function expiryOf(uint _campaignID) public constant returns (uint){
        Campaign c = campaigns[_campaignID];

        return c.expiry;
    }

    function createdAt(uint _campaignID) public constant returns (uint){
        Campaign c = campaigns[_campaignID];

        return c.created;
    }

    function totalContributors(uint _campaignID) public constant returns (uint){
        Campaign c = campaigns[_campaignID];

        return c.numContributors;
    }

    function isOwner(uint _campaignID, address _owner) public constant returns (bool){
        Campaign c = campaigns[_campaignID];

        if(c.owner == _owner)
            return true;
    }

    function hasFailed(uint _campaignID) public constant returns (bool){
        Campaign c = campaigns[_campaignID];

        if (now > c.expiry
            && c.amountRaised < c.fundingGoal
            && c.amountRaised > 0)
            return true;
    }

    function isSuccess(uint _campaignID) public constant returns (bool){
        Campaign c = campaigns[_campaignID];

        if (c.amountRaised >= c.fundingGoal)
            return true;
    }

    function isPaidOut(uint _campaignID) public constant returns (bool){
        Campaign c = campaigns[_campaignID];

        return c.paidOut;
    }

    function totalRefunded(uint _campaignID) public constant returns (uint){
        Campaign c = campaigns[_campaignID];
        uint refunded = 0;

        if(!hasFailed(_campaignID))
            return 0;

        for(uint contributorID = 0; contributorID < c.numContributors; contributorID++) {
            if(c.contributors[contributorID].refunded == true)
                refunded += c.contributors[contributorID].amountContributed;
        }

        return refunded;
    }

    function isRefunded(uint _campaignID) public constant returns (bool){
        Campaign c = campaigns[_campaignID];

        for(uint contributorID = 0; contributorID < c.numContributors; contributorID++) {
            if(c.contributors[contributorID].refunded != true)
                return false;
        }

        return true;
    }
}