Update IdentityManager.sol

Update IdentityManager.sol

contrato IdentityManager

pragma solidity ^0.4.4;

contract IdentityManager{

    //nombre pasado al constructor.
    bytes32 public name;

    //direccion del creador del contrato.
    address public direction;

    //Arrays donde se guardan todos los usuarios y aplicaciones registrados.
    bytes32[] Allusers;
    bytes32[] Allapps;

    //Struct que identifica a un usuario.
    struct User{
        bytes32 nombre;
        address direccion;
        bytes32[] roles;
        address[] aplicacionesaddr;
    }

    //Struct que identifica a una aplicación.
    struct App{
        bytes32 nombre;
        address direccion;
        bytes32[] roles;
    }

    //Struct que almacena el rol, el token (hash) y la aplicación en la que se podrá registrar un usuario
    struct Controlador{
        address direccionApp;
        bytes32 hash;
        bytes32 rol;
    }

    //almacén donde se encuentran todos los usuarios registrados.
    mapping(address => User) public users;

    //almacén donde se encuentran las app registradas.
    mapping(bytes32 => App) public apps;

    //almacén donde se relacionan los nombres de usuario con sus direcciones.
    mapping(bytes32 => address) public relacionUsuarios;

    //almacén donde se relacionan las direcciones de las aps con los nombres.
    mapping(address => bytes32) public relacionApps;

    //almacén donde se guarda cada usuario con la información que tiene que usar para registrarse.
    mapping(address => Controlador) public controlador;

    //Constructor
    function IdentityManager(bytes32 _name){
        name = _name;
        direction = msg.sender;
    }

    //eventos
    event NewUser(address key);
    event WrongRole(string mensaje);
    event Result(bytes32 result);
    event Resultado ( bool a);
    event Array(bytes32[] array);
    event ArrayAddr(address[] array);
    event Resultstring(string);
    event MalNombreApp(string);

     //funcion a la que se llama cuando se registra un usuario, se indica el nombre de usuario, la aplicación en la que se registra y el token.
    function registrarUsuario(bytes32 rol1, bytes32 nickname, bytes32 aplicacion, bytes32 token) {
        if(users[msg.sender].nombre != ""){
            if(users[msg.sender].nombre != nickname ){
            Resultstring("su nombre de usuario no es correcto");
            return;
            }
        }
        address vbladdr = devuelveAppaddr(aplicacion);
        if((controlador[msg.sender].hash == token)&&(vbladdr == controlador[msg.sender].direccionApp)&&(rol1 == controlador[msg.sender].rol)){
             //address vbladdr = apps[aplicacion].direccion;

        if( apps[aplicacion].nombre != ""){
            bool noRegistrado = true;
            for(uint a = 0; a < users[msg.sender].aplicacionesaddr.length; a++){
                if(users[msg.sender].aplicacionesaddr[a] == vbladdr){
                    noRegistrado = false;
                }

            }
            if(noRegistrado){
                relacionUsuarios[nickname] = msg.sender;
            for(uint i = 0; i< apps[aplicacion].roles.length; i++){

                if(apps[aplicacion].roles[i] == rol1){

                    bytes32[] rolesAux = users[msg.sender].roles;
                    rolesAux.push(rol1);
                    address[] aplicacionesAux = users[msg.sender].aplicacionesaddr;
                    aplicacionesAux.push(vbladdr);
                    users[msg.sender] = User({nombre:nickname, direccion:msg.sender, roles:rolesAux, aplicacionesaddr : aplicacionesAux});

                    Result(users[msg.sender].roles[users[msg.sender].roles.length - 1]);
                     NewUser(users[msg.sender].aplicacionesaddr[users[msg.sender].aplicacionesaddr.length - 1]);
                     bool esta = false;
                     for(uint p = 0; p< Allusers.length; p++){
                        if(Allusers[p]==nickname){
                            esta = true;
                        }

                     }
                     if(!esta){
                        Allusers.push(nickname);

                     }

                }else if (i == (apps[aplicacion].roles.length - 1) ){
                    WrongRole("El rol introducido no es valido");
                }

            }
            }else{
                Result("Ya está registrado en esa app");
            }

         }else{throw;}

        }else{
            Result("Token malo");
        }
    }

    //variables necesarias eliminar un registro de un usuario en una aplicación.
    address[] almacenApps;
    address[] almacenApps1;
    bytes32[] almacenRoles;
    bytes32[] almacenRoles1;

    //función que permite eliminar un registro de un usuario en una aplicación.
    function borrarRegistro(bytes32 nickname,bytes32 aplicacion){

        address vbladdr = devuelveAppaddr(aplicacion);
        for(uint a = 0; a < users[msg.sender].aplicacionesaddr.length; a++){
                if(users[msg.sender].aplicacionesaddr[a] != vbladdr){
                    almacenApps.push(users[msg.sender].aplicacionesaddr[a]);
                    almacenRoles.push(users[msg.sender].roles[a]);
                }
            }
        users[msg.sender].aplicacionesaddr = almacenApps;
        users[msg.sender].roles = almacenRoles;
        almacenApps = almacenApps1;
        almacenRoles = almacenRoles1;

      }

    //función que permite registrar una aplicación en el gestor.
    function registrarApp(bytes32 aplicacion,address a, bytes32[] b) {
        if(apps[aplicacion].nombre ==""){
        apps[aplicacion] = App({nombre:aplicacion, direccion:a, roles:b});
        relacionApps[a] = aplicacion;
        Result("App registrada correctamente");
        Allapps.push(aplicacion);

        }else{
            MalNombreApp("debe registrar su aplicación con otro nombre");
        }

    }

    //función que devuelve todos los usuarios registrados
    function  devuelveUsers() returns(bytes32[]){
        return Allusers;
    }

    //función que devuelve todas las apps registradas
    function  devuelveTodasApps() returns(bytes32[]){
        return Allapps;
    }

    //función que devuelve una dirección de una aplicación de la que se conoce su nombre.
    function devuelveAppaddr(bytes32 aplicacion) returns (address){
       return apps[aplicacion].direccion;
    }

    //función que devuelve los roles posibles de una aplicación.
    function devuelveApproles(bytes32 aplicacion) returns (bytes32[]){
       return apps[aplicacion].roles;
    }

    //función que permite comprobar si un usuario tiene un rol determinado.
    function comprueba(address a, bytes32 rol) returns (bool isRegistered){

        for(uint i = 0; i< users[a].aplicacionesaddr.length; i++){
            if(users[a].aplicacionesaddr[i] == msg.sender){
                if(users[a].roles[i] == rol){
                    isRegistered = true;
                    Resultado(isRegistered);
                    return isRegistered;

                }else{
                    isRegistered = false;
                    Resultado(isRegistered);
                    return isRegistered;

                }

            }else{
                isRegistered == false;
            }

       }
       Resultado(isRegistered);
            return isRegistered;
    }

    //función que usan las aplicaciones para indicar el token de un usuario y el rol en el que se pueden registrar.
     function controla(address user, bytes32 hash, bytes32 rol){
     controlador[user].hash = hash;
     controlador[user].direccionApp = msg.sender;
     controlador[user].rol = rol;
     Result("Token de Usuario registrado");
    }

    //función que devuelve los roles de un usuario
    function devuelveRoles(bytes32 user) returns (bytes32[] rolesuser){
        address usuario = relacionUsuarios[user];
        if(msg.sender != usuario){
        Resultstring("Info privada");
        return;
        }
        rolesuser = users[usuario].roles;
        Array(rolesuser);
        return rolesuser;
    }

    //función que devuelve las aplicaciones donde se ha registrado un usuario.
    function devuelveApps(bytes32 user) returns (address[] appsuser){
        address usuario = relacionUsuarios[user];
        if(msg.sender != usuario){
        Resultstring("Info privada");
        return;
        }
        appsuser = users[usuario].aplicacionesaddr;
        ArrayAddr(appsuser);
        return appsuser;
     }

     //función que devuelve la dirección de un usuario del que se conoce el nombre.
    function devuelveAddressUsuario(bytes32 user) returns (address){
     return relacionUsuarios[user];
    }

    //función que devuelve el nombre de una aplicación de la que se conoce su dirección.
    function devuelveNombreApp(address app) returns (bytes32){
     return relacionApps[app];
    }

}

pragma solidity ^0.4.4;

contract IdentityManager{

    //nombre pasado al constructor.
    bytes32 public name;

    //direccion del creador del contrato.
    address public direction;

    //Arrays donde se guardan todos los usuarios y aplicaciones registrados.
    bytes32[] Allusers;
    bytes32[] Allapps;

    //Struct que identifica a un usuario.
    struct User{
        bytes32 nombre;
        address direccion;
        bytes32[] roles;
        address[] aplicacionesaddr;
    }

    //Struct que identifica a una aplicación.
    struct App{
        bytes32 nombre;
        address direccion;
        bytes32[] roles;
    }

    //Struct que almacena el rol, el token (hash) y la aplicación en la que se podrá registrar un usuario
    struct Controlador{
        address direccionApp;
        bytes32 hash;
        bytes32 rol;
    }

    //almacén donde se encuentran todos los usuarios registrados.
    mapping(address => User) public users;

    //almacén donde se encuentran las app registradas.
    mapping(bytes32 => App) public apps;

    //almacén donde se relacionan los nombres de usuario con sus direcciones.
    mapping(bytes32 => address) public relacionUsuarios;

    //almacén donde se relacionan las direcciones de las aps con los nombres.
    mapping(address => bytes32) public relacionApps;

    //almacén donde se guarda cada usuario con la información que tiene que usar para registrarse.
    mapping(address => Controlador) public controlador;

    //Constructor
    function IdentityManager(bytes32 _name){
        name = _name;
        direction = msg.sender;
    }

    //eventos
    event NewUser(address key);
    event WrongRole(string mensaje);
    event Result(bytes32 result);
    event Resultado ( bool a);
    event Array(bytes32[] array);
    event ArrayAddr(address[] array);
    event Resultstring(string);
    event MalNombreApp(string);

     //funcion a la que se llama cuando se registra un usuario, se indica el nombre de usuario, la aplicación en la que se registra y el token.
    function registrarUsuario(bytes32 rol1, bytes32 nickname, bytes32 aplicacion, bytes32 token) {
        if(users[msg.sender].nombre != ""){
            if(users[msg.sender].nombre != nickname ){
            Resultstring("su nombre de usuario no es correcto");
            return;
            }
        }
        address vbladdr = devuelveAppaddr(aplicacion);
        if((controlador[msg.sender].hash == token)&&(vbladdr == controlador[msg.sender].direccionApp)&&(rol1 == controlador[msg.sender].rol)){
             //address vbladdr = apps[aplicacion].direccion;

        if( apps[aplicacion].nombre != ""){
            bool noRegistrado = true;
            for(uint a = 0; a < users[msg.sender].aplicacionesaddr.length; a++){
                if(users[msg.sender].aplicacionesaddr[a] == vbladdr){
                    noRegistrado = false;
                }

            }
            if(noRegistrado){
                relacionUsuarios[nickname] = msg.sender;
            for(uint i = 0; i< apps[aplicacion].roles.length; i++){

                if(apps[aplicacion].roles[i] == rol1){

                    bytes32[] rolesAux = users[msg.sender].roles;
                    rolesAux.push(rol1);
                    address[] aplicacionesAux = users[msg.sender].aplicacionesaddr;
                    aplicacionesAux.push(vbladdr);
                    users[msg.sender] = User({nombre:nickname, direccion:msg.sender, roles:rolesAux, aplicacionesaddr : aplicacionesAux});

                    Result(users[msg.sender].roles[users[msg.sender].roles.length - 1]);
                     NewUser(users[msg.sender].aplicacionesaddr[users[msg.sender].aplicacionesaddr.length - 1]);
                     bool esta = false;
                     for(uint p = 0; p< Allusers.length; p++){
                        if(Allusers[p]==nickname){
                            esta = true;
                        }

                     }
                     if(!esta){
                        Allusers.push(nickname);

                     }

                }else if (i == 2){
                    WrongRole("El rol introducido no es valido");
                }

            }
            }else{
                Result("Ya está registrado en esa app");
            }

         }else{throw;}

        }else{
            Result("Token malo");
        }
    }

    //variables necesarias eliminar un registro de un usuario en una aplicación.
    address[] almacenApps;
    address[] almacenApps1;
    bytes32[] almacenRoles;
    bytes32[] almacenRoles1;

    //función que permite eliminar un registro de un usuario en una aplicación.
    function borrarRegistro(bytes32 nickname,bytes32 aplicacion){

        address vbladdr = devuelveAppaddr(aplicacion);
        for(uint a = 0; a < users[msg.sender].aplicacionesaddr.length; a++){
                if(users[msg.sender].aplicacionesaddr[a] != vbladdr){
                    almacenApps.push(users[msg.sender].aplicacionesaddr[a]);
                    almacenRoles.push(users[msg.sender].roles[a]);
                }
            }
        users[msg.sender].aplicacionesaddr = almacenApps;
        users[msg.sender].roles = almacenRoles;
        almacenApps = almacenApps1;
        almacenRoles = almacenRoles1;

      }

    //función que permite registrar una aplicación en el gestor.
    function registrarApp(bytes32 aplicacion,address a, bytes32[] b) {
        if(apps[aplicacion].nombre ==""){
        apps[aplicacion] = App({nombre:aplicacion, direccion:a, roles:b});
        relacionApps[a] = aplicacion;
        Result("App registrada correctamente");
        Allapps.push(aplicacion);

        }else{
            MalNombreApp("debe registrar su aplicación con otro nombre");
        }

    }

    //función que devuelve todos los usuarios registrados
    function  devuelveUsers() returns(bytes32[]){
        return Allusers;
    }

    //función que devuelve todas las apps registradas
    function  devuelveTodasApps() returns(bytes32[]){
        return Allapps;
    }

    //función que devuelve una dirección de una aplicación de la que se conoce su nombre.
    function devuelveAppaddr(bytes32 aplicacion) returns (address){
       return apps[aplicacion].direccion;
    }

    //función que devuelve los roles posibles de una aplicación.
    function devuelveApproles(bytes32 aplicacion) returns (bytes32[]){
       return apps[aplicacion].roles;
    }

    //función que permite comprobar si un usuario tiene un rol determinado.
    function comprueba(address a, bytes32 rol) returns (bool isRegistered){

        for(uint i = 0; i< users[a].aplicacionesaddr.length; i++){
            if(users[a].aplicacionesaddr[i] == msg.sender){
                if(users[a].roles[i] == rol){
                    isRegistered = true;
                    Resultado(isRegistered);
                    return isRegistered;

                }else{
                    isRegistered = false;
                    Resultado(isRegistered);
                    return isRegistered;

                }

            }else{
                isRegistered == false;
            }

       }
       Resultado(isRegistered);
            return isRegistered;
    }

    //función que usan las aplicaciones para indicar el token de un usuario y el rol en el que se pueden registrar.
     function controla(address user, bytes32 hash, bytes32 rol){
     controlador[user].hash = hash;
     controlador[user].direccionApp = msg.sender;
     controlador[user].rol = rol;
     Result("Token de Usuario registrado");
    }

    //función que devuelve los roles de un usuario
    function devuelveRoles(bytes32 user) returns (bytes32[] rolesuser){
        address usuario = relacionUsuarios[user];
        if(msg.sender != usuario){
        Resultstring("Info privada");
        return;
        }
        rolesuser = users[usuario].roles;
        Array(rolesuser);
        return rolesuser;
    }

    //función que devuelve las aplicaciones donde se ha registrado un usuario.
    function devuelveApps(bytes32 user) returns (address[] appsuser){
        address usuario = relacionUsuarios[user];
        if(msg.sender != usuario){
        Resultstring("Info privada");
        return;
        }
        appsuser = users[usuario].aplicacionesaddr;
        ArrayAddr(appsuser);
        return appsuser;
     }

     //función que devuelve la dirección de un usuario del que se conoce el nombre.
    function devuelveAddressUsuario(bytes32 user) returns (address){
     return relacionUsuarios[user];
    }

    //función que devuelve el nombre de una aplicación de la que se conoce su dirección.
    function devuelveNombreApp(address app) returns (bytes32){
     return relacionApps[app];
    }

}


updated missing modifier

updated missing modifier

/*
    Copyright 2017 Phillip A. Elsasser

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity ^0.4.18;

import "truffle/Assert.sol";
import "../../contracts/tokens/MarketToken.sol";

/// @title TestMarketToken
/// @author Phil Elsasser <phil@marketprotcol.io>
contract TestMarketToken {

    function testInitialBalance() public {
        MarketToken marketToken = new MarketToken(0, 0);
        Assert.equal(
            marketToken.balanceOf(this),
            marketToken.INITIAL_SUPPLY(),
            "init supply allocated to creator"
        );
    }

    /// @dev tests functionality related to our minimum required balance of tokens in order
    /// to allow users to create a MarketContract
    function testNeededBalanceForContractCreation() public {
        uint neededBalanceForContractCreation = 25;
        MarketToken marketToken = new MarketToken(0, neededBalanceForContractCreation);

        Assert.equal(
            neededBalanceForContractCreation,
            marketToken.minBalanceToAllowContractCreation(),
            "contract requirements don't match from constructor"
        );

        Assert.isTrue(
            marketToken.isBalanceSufficientForContractCreation(this),
            "balance report as insufficient"
        );

        address recipient = 0x123; // fake address to use for testing of sufficient balances

        Assert.equal(
            marketToken.balanceOf(recipient),
            0,
            "balance of new address isn't zero"
        );

        Assert.isTrue(
            !marketToken.isBalanceSufficientForContractCreation(recipient),
            "balance report as sufficient when zero!"
        );

        marketToken.transfer(recipient, neededBalanceForContractCreation);

        Assert.equal(
            marketToken.balanceOf(recipient),
            neededBalanceForContractCreation,
            "balance not transferred correctly"
        );

        Assert.isTrue(
            marketToken.isBalanceSufficientForContractCreation(recipient),
            "balance report as insufficient!"
        );

        // since this contract is the creator we should be able to set a new min balance and then ensure
        // our recipient isn't able to create now
        marketToken.setMinBalanceForContractCreation(neededBalanceForContractCreation + 1);

        Assert.isTrue(
            !marketToken.isBalanceSufficientForContractCreation(recipient),
            "balance report as sufficient after increase!"
        );

        Assert.isTrue(
            marketToken.isBalanceSufficientForContractCreation(this),
            "balance report as insufficient"
        );
    }

    function testLockTokensForTrading() public {
        uint qtyToLockForTrading = 10;
        MarketToken marketToken = new MarketToken(qtyToLockForTrading, 0);

        Assert.equal(
            qtyToLockForTrading,
            marketToken.lockQtyToAllowTrading(),
            "contract requirements don't match from constructor"
        );

        address fakeMarketContractAddress = 0x12345;
        Assert.isTrue(
            !marketToken.isUserEnabledForContract(fakeMarketContractAddress, this),
            "contract shouldn't allow trading without lock"
        );

        marketToken.lockTokensForTradingMarketContract(fakeMarketContractAddress, qtyToLockForTrading);

        Assert.equal(
            qtyToLockForTrading,
            marketToken.getLockedBalanceForUser(fakeMarketContractAddress, this),
            "contract reporting incorrect locked balance"
        );

        Assert.equal(
            marketToken.balanceOf(this),
            marketToken.INITIAL_SUPPLY() - qtyToLockForTrading,
            "balance didn't decrease with lock"
        );

        Assert.isTrue(
            marketToken.isUserEnabledForContract(fakeMarketContractAddress, this),
            "contract should allow trading with locked balance"
        );

        Assert.equal(
            0,
            marketToken.getLockedBalanceForUser(0x100, this),
            "contract reporting incorrect locked balance for fake contract"
        );

        Assert.isTrue(
            marketToken.isUserEnabledForContract(fakeMarketContractAddress, this),
            "user not enabled for contract"
        );

        Assert.isTrue(
            !marketToken.isUserEnabledForContract(0x100, this),
            "user enabled for unknown contract"
        );

        // since we are the creator of the market token, we should be able to change the required lock amount
        // therefore disabling trading based on the lower locked qty
        marketToken.setLockQtyToAllowTrading(qtyToLockForTrading + 1);

        Assert.isTrue(
            !marketToken.isUserEnabledForContract(fakeMarketContractAddress, this),
            "higher lock amount didn't stop user from trading"
        );

        marketToken.unlockTokens(fakeMarketContractAddress, qtyToLockForTrading);

        Assert.equal(
            marketToken.balanceOf(this),
            marketToken.INITIAL_SUPPLY(),
            "balance didn't increase with unlock"
        );

        Assert.equal(
            0,
            marketToken.getLockedBalanceForUser(fakeMarketContractAddress, this),
            "contract reporting incorrect locked balance after unlock"
        );
    }

}

/*
    Copyright 2017 Phillip A. Elsasser

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity ^0.4.18;

import "truffle/Assert.sol";
import "../../contracts/tokens/MarketToken.sol";

/// @title TestMarketToken
/// @author Phil Elsasser <phil@marketprotcol.io>
contract TestMarketToken {

    function testInitialBalance() {
        MarketToken marketToken = new MarketToken(0, 0);
        Assert.equal(
            marketToken.balanceOf(this),
            marketToken.INITIAL_SUPPLY(),
            "init supply allocated to creator"
        );
    }

    /// @dev tests functionality related to our minimum required balance of tokens in order
    /// to allow users to create a MarketContract
    function testNeededBalanceForContractCreation() {
        uint neededBalanceForContractCreation = 25;
        MarketToken marketToken = new MarketToken(0, neededBalanceForContractCreation);

        Assert.equal(
            neededBalanceForContractCreation,
            marketToken.minBalanceToAllowContractCreation(),
            "contract requirements don't match from constructor"
        );

        Assert.isTrue(
            marketToken.isBalanceSufficientForContractCreation(this),
            "balance report as insufficient"
        );

        address recipient = 0x123; // fake address to use for testing of sufficient balances

        Assert.equal(
            marketToken.balanceOf(recipient),
            0,
            "balance of new address isn't zero"
        );

        Assert.isTrue(
            !marketToken.isBalanceSufficientForContractCreation(recipient),
            "balance report as sufficient when zero!"
        );

        marketToken.transfer(recipient, neededBalanceForContractCreation);

        Assert.equal(
            marketToken.balanceOf(recipient),
            neededBalanceForContractCreation,
            "balance not transferred correctly"
        );

        Assert.isTrue(
            marketToken.isBalanceSufficientForContractCreation(recipient),
            "balance report as insufficient!"
        );

        // since this contract is the creator we should be able to set a new min balance and then ensure
        // our recipient isn't able to create now
        marketToken.setMinBalanceForContractCreation(neededBalanceForContractCreation + 1);

        Assert.isTrue(
            !marketToken.isBalanceSufficientForContractCreation(recipient),
            "balance report as sufficient after increase!"
        );

        Assert.isTrue(
            marketToken.isBalanceSufficientForContractCreation(this),
            "balance report as insufficient"
        );
    }

    function testLockTokensForTrading() {
        uint qtyToLockForTrading = 10;
        MarketToken marketToken = new MarketToken(qtyToLockForTrading, 0);

        Assert.equal(
            qtyToLockForTrading,
            marketToken.lockQtyToAllowTrading(),
            "contract requirements don't match from constructor"
        );

        address fakeMarketContractAddress = 0x12345;
        Assert.isTrue(
            !marketToken.isUserEnabledForContract(fakeMarketContractAddress, this),
            "contract shouldn't allow trading without lock"
        );

        marketToken.lockTokensForTradingMarketContract(fakeMarketContractAddress, qtyToLockForTrading);

        Assert.equal(
            qtyToLockForTrading,
            marketToken.getLockedBalanceForUser(fakeMarketContractAddress, this),
            "contract reporting incorrect locked balance"
        );

        Assert.equal(
            marketToken.balanceOf(this),
            marketToken.INITIAL_SUPPLY() - qtyToLockForTrading,
            "balance didn't decrease with lock"
        );

        Assert.isTrue(
            marketToken.isUserEnabledForContract(fakeMarketContractAddress, this),
            "contract should allow trading with locked balance"
        );

        Assert.equal(
            0,
            marketToken.getLockedBalanceForUser(0x100, this),
            "contract reporting incorrect locked balance for fake contract"
        );

        Assert.isTrue(
            marketToken.isUserEnabledForContract(fakeMarketContractAddress, this),
            "user not enabled for contract"
        );

        Assert.isTrue(
            !marketToken.isUserEnabledForContract(0x100, this),
            "user enabled for unknown contract"
        );

        // since we are the creator of the market token, we should be able to change the required lock amount
        // therefore disabling trading based on the lower locked qty
        marketToken.setLockQtyToAllowTrading(qtyToLockForTrading + 1);

        Assert.isTrue(
            !marketToken.isUserEnabledForContract(fakeMarketContractAddress, this),
            "higher lock amount didn't stop user from trading"
        );

        marketToken.unlockTokens(fakeMarketContractAddress, qtyToLockForTrading);

        Assert.equal(
            marketToken.balanceOf(this),
            marketToken.INITIAL_SUPPLY(),
            "balance didn't increase with unlock"
        );

        Assert.equal(
            0,
            marketToken.getLockedBalanceForUser(fakeMarketContractAddress, this),
            "contract reporting incorrect locked balance after unlock"
        );
    }

}


Rebuilt Rules.sol

Rebuilt Rules.sol

import "Adjudicator";
import "LockedState";

contract Rules {

	event StateChannelCreated(address Adjudicator, address LockedState);

	Adjudicator adjudicator;

	function Rules() {
		adjudicator = createAdjudicator();
		StateChannelCreated(adjudicator, adjudicator.getLockedStateAddress());
	}

	function createAdjudicator() internal returns (Adjudicator);

	// you may define the rules and exposure conditions of the state channel
	// in a subcontract that inherits from this contract
}

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


Remove default MetaCoin contract

Remove default MetaCoin contract

pragma solidity ^0.4.4;

import "./ConvertLib.sol";

// This is just a simple example of a coin-like contract.
// It is not standards compatible and cannot be expected to talk to other
// coin/token contracts. If you want to create a standards-compliant
// token, see: https://github.com/ConsenSys/Tokens. Cheers!

contract MetaCoin {
	mapping (address => uint) balances;

	event Transfer(address indexed _from, address indexed _to, uint256 _value);

	function MetaCoin() {
		balances[tx.origin] = 10000;
	}

	function sendCoin(address receiver, uint amount) returns(bool sufficient) {
		if (balances[msg.sender] < amount) return false;
		balances[msg.sender] -= amount;
		balances[receiver] += amount;
		Transfer(msg.sender, receiver, amount);
		return true;
	}

	function getBalanceInEth(address addr) returns(uint){
		return ConvertLib.convert(getBalance(addr),2);
	}

	function getBalance(address addr) returns(uint) {
		return balances[addr];
	}
}


catalogo: converter demais retornos em string

pragma solidity ^0.4.11;

/// @title Catalogo de Ouvidorias para o Barramento de Ouvidorias
contract CatalogoOuvidorias {

    enum TipoEnte { Uniao, Estado, Municipio }

    struct Ente {
        TipoEnte tipo;
        bytes32 nome;   // nome do ente, caso se aplique (Uniao nao eh necessario). Ex.: 'Bahia', 'Salvador-BA'
    }

    struct Ouvidoria {
        address conta; // account Ethereum desta ouvidoria
        bytes32 nome;   // nome do orgao
        Ente ente; // ente a qual a ouvidoria pertence
        bytes32 endpoint;   // URL da aplicacao/web service desta ouvidoria
    }

    address[] enderecosOuvidorias;

    mapping(address => Ouvidoria) private ouvidorias;

    mapping(address => uint8) public candidatas;

    event ouvidoriasAtualizadas(address conta, bytes32 nome, uint8 tipoEnte, bytes32 nomeEnte, bytes32 endpoint);

    /// Cria o catalogo com uma ouvidoria -- nao exigi tres porque seriam tantas variaveis que o solarity nao permite:
    /// Compiler error (...): Stack too deep, try removing local variables.
    function CatalogoOuvidorias(bytes32 nome, uint8 tipoEnte, bytes32 nomeEnte, bytes32 endpoint) {
        ouvidorias[msg.sender] = Ouvidoria({
            conta: msg.sender,
            nome: nome,
            ente: Ente({tipo: toTipoEnte(tipoEnte), nome: nomeEnte}),
            endpoint: endpoint
        });
        enderecosOuvidorias.push(msg.sender);
    }

    function toTipoEnte(uint8 tipo) returns (TipoEnte) {
        if (tipo == 0) return TipoEnte.Uniao;
        if (tipo == 1) return TipoEnte.Estado;
        if (tipo == 2) return TipoEnte.Municipio;
        throw;
    }

    function getNumeroDeOuvidorias() constant returns (uint) {
        return enderecosOuvidorias.length;
    }

    function getEnderecoOuvidoria(uint i) constant returns (address) {
        return enderecosOuvidorias[i];
    }

    function getOuvidoriaNome(address ouvidoria) constant returns (string) {
        return toString(ouvidorias[ouvidoria].nome);
    }

    function getOuvidoriaEndpoint(address ouvidoria) constant returns (string) {
        return toString(ouvidorias[ouvidoria].endpoint);
    }

    function getOuvidoriaEnteTipo(address ouvidoria) constant returns (uint) {
        return uint(ouvidorias[ouvidoria].ente.tipo);
    }

    function getOuvidoriaEnteNome(address ouvidoria) constant returns (string) {
        return toString(ouvidorias[ouvidoria].ente.nome);
    }

    // Uma ouvidoria cadastrada pode votar em outra
    function votar(address ouvidoriaCandidata) {
        log1('votando', '2');
    }

    // converte bytes32 em string
    function toString(bytes32 x) constant returns (string) {
        bytes memory bytesString = new bytes(32);
        uint charCount = 0;
        for (uint j = 0; j < 32; j++) {
            byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[charCount] = char;
                charCount++;
            }
        }
        bytes memory bytesStringTrimmed = new bytes(charCount);
        for (j = 0; j < charCount; j++) {
            bytesStringTrimmed[j] = bytesString[j];
        }
        return string(bytesStringTrimmed);
    }

}

pragma solidity ^0.4.11;

/// @title Catalogo de Ouvidorias para o Barramento de Ouvidorias
contract CatalogoOuvidorias {

    enum TipoEnte { Uniao, Estado, Municipio }

    struct Ente {
        TipoEnte tipo;
        bytes32 nome;   // nome do ente, caso se aplique (Uniao nao eh necessario). Ex.: 'Bahia', 'Salvador-BA'
    }

    struct Ouvidoria {
        address conta; // account Ethereum desta ouvidoria
        bytes32 nome;   // nome do orgao
        Ente ente; // ente a qual a ouvidoria pertence
        bytes32 endpoint;   // URL da aplicacao/web service desta ouvidoria
    }

    address[] enderecosOuvidorias;

    mapping(address => Ouvidoria) private ouvidorias;

    mapping(address => uint8) public candidatas;

    event ouvidoriasAtualizadas(address conta, bytes32 nome, uint8 tipoEnte, bytes32 nomeEnte, bytes32 endpoint);

    /// Cria o catalogo com uma ouvidoria -- nao exigi tres porque seriam tantas variaveis que o solarity nao permite:
    /// Compiler error (...): Stack too deep, try removing local variables.
    function CatalogoOuvidorias(bytes32 nome, uint8 tipoEnte, bytes32 nomeEnte, bytes32 endpoint) {
        ouvidorias[msg.sender] = Ouvidoria({
            conta: msg.sender,
            nome: nome,
            ente: Ente({tipo: toTipoEnte(tipoEnte), nome: nomeEnte}),
            endpoint: endpoint
        });
        enderecosOuvidorias.push(msg.sender);
    }

    function toTipoEnte(uint8 tipo) returns (TipoEnte) {
        if (tipo == 0) return TipoEnte.Uniao;
        if (tipo == 1) return TipoEnte.Estado;
        if (tipo == 2) return TipoEnte.Municipio;
        throw;
    }

    function getNumeroDeOuvidorias() constant returns (uint) {
        return enderecosOuvidorias.length;
    }

    function getEnderecoOuvidoria(uint i) constant returns (address) {
        return enderecosOuvidorias[i];
    }

    function getOuvidoriaNome(address ouvidoria) constant returns (bytes32) {
        return ouvidorias[ouvidoria].nome;
    }

    function getOuvidoriaEndpoint(address ouvidoria) constant returns (bytes32) {
        return ouvidorias[ouvidoria].endpoint;
    }

    function getOuvidoriaEnteTipo(address ouvidoria) constant returns (uint) {
        return uint(ouvidorias[ouvidoria].ente.tipo);
    }

    function getOuvidoriaEnteNome(address ouvidoria) constant returns (string) {
        return toS(ouvidorias[ouvidoria].ente.nome);
    }

    // Uma ouvidoria cadastrada pode votar em outra
    function votar(address ouvidoriaCandidata) {
        log1('votando', '2');
    }

    // converte bytes32 em string
    function toS(bytes32 x) constant returns (string) {
        bytes memory bytesString = new bytes(32);
        uint charCount = 0;
        for (uint j = 0; j < 32; j++) {
            byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[charCount] = char;
                charCount++;
            }
        }
        bytes memory bytesStringTrimmed = new bytes(charCount);
        for (j = 0; j < charCount; j++) {
            bytesStringTrimmed[j] = bytesString[j];
        }
        return string(bytesStringTrimmed);
    }

}


Refactors `addUser` to prevent overwrite, adds `updateUser` func

import "SequenceList.sol";
import "User.sol";

contract UserManager {
    SequenceList list = new SequenceList();

    /* TODO extend with eventObject if possible; `bytes32[]`? */
    event ActionEvent(address indexed userAddr, bytes32 actionType);
    function registerActionEvent(bytes32 actionType) {
      ActionEvent(msg.sender, actionType);
    }

    function addUser(
        bytes32 _id,
        bytes32 _username,
        bytes32 _email,
        bytes32 _name,
        bytes32 _score,
        bytes32 _teamId,
        bytes32 _passwHash
        )
        returns (address)
        {
            registerActionEvent("ADD USER");
            // index on `username` for User map for account retrieval on login
            bytes32 key = _username;
            User u = new User(_id, _username, _email, _name, _score, _teamId, _passwHash);

            bool isOverwrite = list.exists(key);
            // if this would be an overwrite -> return null address
            if (isOverwrite) {
                return 0x0;
            } else {
                list.insert(key, u);
                return u;
            }
    }

    function updateUser(
        bytes32 _id,
        bytes32 _username,
        bytes32 _email,
        bytes32 _name,
        bytes32 _score,
        bytes32 _teamId,
        bytes32 _passwHash
        )
        returns (bool success)
        {
            registerActionEvent("UPDATE USER");
            // index on `username` for User map for account retrieval on login
            bytes32 key = _username;
            User u = new User(_id, _username, _email, _name, _score, _teamId, _passwHash);

            bool exists = list.exists(key);
            // if record does not exist -> return null address
            if (!exists) {
                return false;
            } else {
                bool isOverwrite = list.insert(key, u);
                return isOverwrite;
            }
        }

    function getUserListSize() constant returns (uint) {
        registerActionEvent("GET USERLIST SIZE");
        return list.size();

    }

    function getUserAddress(bytes32 username) returns (address) {
        registerActionEvent("LINK TO TASK");
        return list.value(username);
    }
}

import "SequenceList.sol";
import "User.sol";

contract UserManager {
    SequenceList list = new SequenceList();

    // TODO extend with eventObject if possible; `bytes32[]`?
    event ActionEvent(address indexed userAddr, bytes32 actionType);
    function registerActionEvent(bytes32 actionType) {
      ActionEvent(msg.sender, actionType);
    }

    // TODO ensure there can't be overwrites from addUser -> make it proper CRUD
    function addUser(
        bytes32 _id,
        bytes32 _username,
        bytes32 _email,
        bytes32 _name,
        bytes32 _score,
        bytes32 _teamId,
        bytes32 _passwHash
        )
        returns (User u)
        {
            registerActionEvent("ADD USER");
            u = new User(_id, _username, _email, _name, _score, _teamId, _passwHash);

            // index on `username` for User map for account retrieval on login
            bool isOverwrite = list.insert(_username, u);
            // TODO needs a verification of insert success
            return u;
    }

    function getUserListSize() constant returns (uint) {
        registerActionEvent("GET USERLIST SIZE");
        return list.size();

    }

    function getUserAddress(bytes32 username) returns (address) {
        registerActionEvent("LINK TO TASK");
        return list.value(username);
    }
}


Rebuild memory and storage arrays

Rebuild memory and storage arrays

pragma solidity ^0.4.8;
import "./usingOraclize.sol";
import "./AbstractArbiter.sol";

contract ComputationService is usingOraclize {
  struct Query {
    string URL;
    string JSON;
  }
  mapping(uint => Query) public computation;

  struct Request {
    string input1;
    string input2;
    uint operation;
    uint256 computationId;
    string result;
    address arbiter;
  }

  mapping(uint256 => bytes32) public requestId;
  mapping(bytes32 => Request) public requestOraclize;

  address public arbiter;

  event newOraclizeQuery(string description);
  event newResult(string comp_result);
  event newOraclizeID(bytes32 ID);

  function ComputationService() {
    OAR = OraclizeAddrResolverI(0x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475);
  }

  function __callback(bytes32 _oraclizeID, string _result) {
    if (msg.sender != oraclize_cbAddress()) throw;
    newResult(_result);

    requestOraclize[_oraclizeID].result = _result;

    // send result to arbiter contract
    /*AbstractArbiter myArbiter = AbstractArbiter(requestOraclize[_oraclizeID].arbiter);
    myArbiter.receiveResults(_result, requestOraclize[_oraclizeID].computationId);*/
  }

  function compute(string _val1, string _val2, uint _operation, uint256 _computationId) payable {
    bytes32 oraclizeID;

    computation[_operation].JSON = strConcat('\n{"val1": ', _val1, ', "val2": ', _val2, '}');

    newOraclizeQuery("Oraclize query was sent, standing by for the answer.");

    oraclizeID = oraclize_query(60, "URL", computation[_operation].URL, computation[_operation].JSON);

    // store address for specific request
    requestOraclize[oraclizeID].input1 = _val1;
    requestOraclize[oraclizeID].input2 = _val2;
    requestOraclize[oraclizeID].operation = _operation;
    requestOraclize[oraclizeID].computationId = _computationId;
    requestOraclize[oraclizeID].arbiter = msg.sender;

    requestId[_computationId] = oraclizeID;

    newOraclizeID(oraclizeID);
  }

  function provideIndex(string _resultSolver, uint _computationId) {
    // this is for two intergers: always returns 0 and 1 for two two intergers
    Request memory _request = requestOraclize[requestId[_computationId]];

    AbstractArbiter myArbiter = AbstractArbiter(msg.sender);
    myArbiter.receiveIndex(0, 1, _request.operation, _request.computationId, true);
  }

  function registerOperation(uint _operation) payable {
    // operation 0: add two integers
    if (_operation == 0) {
      Query memory twoInt = Query("https://r98ro6hfj5.execute-api.eu-west-1.amazonaws.com/test/int", "");
      computation[0] = twoInt;
    }
  }

  function enableArbiter(address _arbiterAddress) payable {
    arbiter = _arbiterAddress;
    AbstractArbiter myArbiter = AbstractArbiter(_arbiterAddress);
    myArbiter.enableService();
  }

  function disableArbiter(address _arbiterAddress) payable {
    delete arbiter;
    AbstractArbiter myArbiter = AbstractArbiter(_arbiterAddress);
    myArbiter.disableService();
  }

  function getResult(bytes32 _oraclizeID) constant returns (string) {
    return requestOraclize[_oraclizeID].result;
  }
}

pragma solidity ^0.4.8;
import "./usingOraclize.sol";
import "./AbstractArbiter.sol";

contract ComputationService is usingOraclize {
  struct Query {
    string URL;
    string JSON;
  }
  mapping(uint => Query) public computation;

  struct Request {
    string input1;
    string input2;
    uint operation;
    uint256 computationId;
    string result;
    address arbiter;
  }

  mapping(uint256 => bytes32) public requestId;
  mapping(bytes32 => Request) public requestOraclize;

  address public arbiter;

  event newOraclizeQuery(string description);
  event newResult(string comp_result);
  event newOraclizeID(bytes32 ID);

  function ComputationService() {
    OAR = OraclizeAddrResolverI(0x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475);
  }

  function __callback(bytes32 _oraclizeID, string _result) {
    if (msg.sender != oraclize_cbAddress()) throw;
    newResult(_result);

    Request memory _request = requestOraclize[_oraclizeID];
    _request.result = _result;

    requestOraclize[_oraclizeID] = _request;

    // send result to arbiter contract
    AbstractArbiter myArbiter = AbstractArbiter(requestOraclize[_oraclizeID].arbiter);
    myArbiter.receiveResults(_result, requestOraclize[_oraclizeID].computationId);
  }

  function compute(string _val1, string _val2, uint _operation, uint256 _computationId) payable {
    bytes32 oraclizeID;

    Query memory _query = computation[_operation];
    _query.JSON = strConcat('\n{"val1": ', _val1, ', "val2": ', _val2, '}');

    newOraclizeQuery("Oraclize query was sent, standing by for the answer.");
    oraclizeID = oraclize_query(60, "URL", _query.URL, _query.JSON);

    // store address for specific request
    Request memory _request;
    _request.input1 = _val1;
    _request.input2 = _val2;
    _request.operation = _operation;
    _request.computationId = _computationId;
    _request.arbiter = msg.sender;

    requestId[_computationId] = oraclizeID;
    requestOraclize[oraclizeID] = _request;

    newOraclizeID(oraclizeID);
  }

  function provideIndex(string _resultSolver, uint _computationId) {
    // this is for two intergers: always returns 0 and 1 for two two intergers
    Request memory _request = requestOraclize[requestId[_computationId]];

    AbstractArbiter myArbiter = AbstractArbiter(msg.sender);
    myArbiter.receiveIndex(0, 1, _request.operation, _request.computationId, true);
  }

  function registerOperation(uint _operation) payable {
    // operation 0: add two integers
    if (_operation == 0) {
      Query memory twoInt = Query("https://r98ro6hfj5.execute-api.eu-west-1.amazonaws.com/test/int", "");
      computation[0] = twoInt;
    }
  }

  function enableArbiter(address _arbiterAddress) payable {
    arbiter = _arbiterAddress;
    AbstractArbiter myArbiter = AbstractArbiter(_arbiterAddress);
    myArbiter.enableService();
  }

  function disableArbiter(address _arbiterAddress) payable {
    delete arbiter;
    AbstractArbiter myArbiter = AbstractArbiter(_arbiterAddress);
    myArbiter.disableService();
  }

  function getResult(bytes32 _oraclizeID) constant returns (string) {
    return requestOraclize[_oraclizeID].result;
  }
}


Added indexed to TradeListing and OwnerWithdrewERC20Token addresses

pragma solidity ^0.4.4;

// ------------------------------------------------------------------------
// TokenSellerFactory
//
// Decentralised trustless ERC20-partially-compliant token to ETH exchange
// contract on the Ethereum blockchain.
//
// This caters for the Golem Network Token which does not implement the
// ERC20 transferFrom(...), approve(...) and allowance(...) methods
//
// Enjoy. (c) JonnyLatte, Cintix & BokkyPooBah 2016. The MIT licence.
// ------------------------------------------------------------------------

// https://github.com/ethereum/EIPs/issues/20
contract ERC20Partial {
    function totalSupply() constant returns (uint totalSupply);
    function balanceOf(address _owner) constant returns (uint balance);
    function transfer(address _to, uint _value) returns (bool success);
    // function transferFrom(address _from, address _to, uint _value) returns (bool success);
    // function approve(address _spender, uint _value) returns (bool success);
    // function allowance(address _owner, address _spender) constant returns (uint remaining);
    event Transfer(address indexed _from, address indexed _to, uint _value);
    // event Approval(address indexed _owner, address indexed _spender, uint _value);
}

contract Owned {
    address public owner;
    event OwnershipTransferred(address indexed _from, address indexed _to);

    function Owned() {
        owner = msg.sender;
    }

    modifier onlyOwner {
        if (msg.sender != owner) throw;
        _;
    }

    function transferOwnership(address newOwner) onlyOwner {
        OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }
}

// contract can sell tokens for ETH
// prices are in amount of wei per batch of token units

contract TokenSeller is Owned {

    address public asset;       // address of token
    uint256 public sellPrice;   // contract sells lots of tokens at this price
    uint256 public units;       // lot size (token-wei)

    bool public sellsTokens;    // is contract selling

    event ActivatedEvent(bool sells);
    event MakerWithdrewAsset(uint256 tokens);
    event MakerWithdrewERC20Token(address tokenAddress, uint256 tokens);
    event MakerWithdrewEther(uint256 ethers);
    event TakerBoughtAsset(address indexed buyer, uint256 ethersSent,
        uint256 ethersReturned, uint256 tokensBought);

    // Constructor - only to be called by the TokenSellerFactory contract
    function TokenSeller (
        address _asset,
        uint256 _sellPrice,
        uint256 _units,
        bool    _sellsTokens
    ) internal {
        asset       = _asset;
        sellPrice   = _sellPrice;
        units       = _units;
        sellsTokens = _sellsTokens;
        ActivatedEvent(sellsTokens);
    }

    // Maker can activate or deactivate this contract's
    // selling status
    //
    // The ActivatedEvent() event is logged with the following
    // parameter:
    //   sellsTokens  this contract can sell asset tokens
    function activate (
        bool _sellsTokens
    ) onlyOwner {
        sellsTokens = _sellsTokens;
        ActivatedEvent(sellsTokens);
    }

    // Maker can withdraw asset tokens from this contract, with the
    // following parameter:
    //   tokens  is the number of asset tokens to be withdrawn
    //
    // The MakerWithdrewAsset() event is logged with the following
    // parameter:
    //   tokens  is the number of tokens withdrawn by the maker
    //
    // This method was called withdrawAsset() in the old version
    function makerWithdrawAsset(uint256 tokens) onlyOwner returns (bool ok) {
        MakerWithdrewAsset(tokens);
        return ERC20Partial(asset).transfer(owner, tokens);
    }

    // Maker can withdraw any ERC20 asset tokens from this contract
    //
    // This method is included in the case where this contract receives
    // the wrong tokens
    //
    // The MakerWithdrewERC20Token() event is logged with the following
    // parameter:
    //   tokenAddress  is the address of the tokens withdrawn by the maker
    //   tokens        is the number of tokens withdrawn by the maker
    //
    // This method was called withdrawToken() in the old version
    function makerWithdrawERC20Token(
        address tokenAddress,
        uint256 tokens
    ) onlyOwner returns (bool ok) {
        MakerWithdrewERC20Token(tokenAddress, tokens);
        return ERC20Partial(tokenAddress).transfer(owner, tokens);
    }

    // Maker withdraws ethers from this contract
    //
    // The MakerWithdrewEther() event is logged with the following parameter
    //   ethers  is the number of ethers withdrawn by the maker
    //
    // This method was called withdraw() in the old version
    function makerWithdrawEther(uint256 ethers) onlyOwner returns (bool ok) {
        if (this.balance >= ethers) {
            MakerWithdrewEther(ethers);
            return owner.send(ethers);
        }
    }

    // Taker buys asset tokens by sending ethers
    //
    // The TakerBoughtAsset() event is logged with the following parameters
    //   buyer           is the buyer's address
    //   ethersSent      is the number of ethers sent by the buyer
    //   ethersReturned  is the number of ethers sent back to the buyer as
    //                   change
    //   tokensBought    is the number of asset tokens sent to the buyer
    //
    // This method was called buy() in the old version
    function takerBuyAsset() payable {
        if (sellsTokens || msg.sender == owner) {
            uint order    = msg.value / sellPrice;
            uint can_sell = ERC20Partial(asset).balanceOf(address(this)) / units;
            uint256 change = 0;
            if (order > can_sell) {
                change = msg.value - (can_sell * sellPrice);
                order = can_sell;
                if (!msg.sender.send(change)) throw;
            }
            if (order > 0) {
                if(!ERC20Partial(asset).transfer(msg.sender, order * units)) throw;
            }
            TakerBoughtAsset(msg.sender, msg.value, order * units, change);
        }
        // Return user funds if the contract is not selling
        else if (!msg.sender.send(msg.value)) throw;
    }

    // Taker buys tokens by sending ethers
    function () payable {
        takerBuyAsset();
    }
}

// This contract deploys TokenSeller contracts and logs the event
contract TokenSellerFactory is Owned {

    event TradeListing(address indexed ownerAddress, address indexed tokenSellerAddress,
        address indexed asset, uint256 sellPrice, uint256 units, bool sellsTokens);
    event OwnerWithdrewERC20Token(address indexed tokenAddress, uint256 tokens);

    mapping(address => bool) _verify;

    // Anyone can call this method to verify the settings of a
    // TokenSeller contract. The parameters are:
    //   tradeContract  is the address of a TokenSeller contract
    //
    // Return values:
    //   valid        did this TokenTraderFactory create the TokenTrader contract?
    //   owner        is the owner of the TokenTrader contract
    //   asset        is the ERC20 asset address
    //   sellPrice    is the sell price in ethers per `units` of asset tokens
    //   units        is the number of units of asset tokens
    //   sellsTokens  is the TokenTrader contract selling tokens?
    //
    function verify(address tradeContract) constant returns (
        bool    valid,
        address owner,
        address asset,
        uint256 sellPrice,
        uint256 units,
        bool    sellsTokens
    ) {
        valid = _verify[tradeContract];
        if (valid) {
            TokenSeller t = TokenSeller(tradeContract);
            owner         = t.owner();
            asset         = t.asset();
            sellPrice     = t.sellPrice();
            units         = t.units();
            sellsTokens   = t.sellsTokens();
        }
    }

    // Maker can call this method to create a new TokenSeller contract
    // with the maker being the owner of this new contract
    //
    // Parameters:
    //   asset        is the ERC20 asset address
    //   sellPrice    is the sell price in ethers per `units` of asset tokens
    //   units        is the number of units of asset tokens
    //   sellsTokens  is the TokenSeller contract selling tokens?
    //
    // For example, listing a TokenSeller contract on the GNT Golem Network Token
    // where the contract will sell GNT tokens at a rate of 170/100000 = 0.0017 ETH
    // per GNT token:
    //   asset        0xa74476443119a942de498590fe1f2454d7d4ac0d
    //   sellPrice    170
    //   units        100000
    //   sellsTokens  true
    //
    // The TradeListing() event is logged with the following parameters
    //   ownerAddress        is the Maker's address
    //   tokenSellerAddress  is the address of the newly created TokenSeller contract
    //   asset               is the ERC20 asset address
    //   sellPrice           is the sell price in ethers per `units` of asset tokens
    //   unit                is the number of units of asset tokens
    //   sellsTokens         is the TokenSeller contract selling tokens?
    //
    // This method was called createTradeContract() in the old version
    //
    function createSaleContract(
        address asset,
        uint256 sellPrice,
        uint256 units,
        bool    sellsTokens
    ) returns (address seller) {
        // Cannot set zero or negative price
        if (sellPrice <= 0) throw;
        // Cannot sell zero or negative units
        if (units <= 0) throw;
        seller = new TokenSeller(
            asset,
            sellPrice,
            units,
            sellsTokens);
        // Record that this factory created the trader
        _verify[seller] = true;
        // Set the owner to whoever called the function
        TokenSeller(seller).transferOwnership(msg.sender);
        TradeListing(msg.sender, seller, asset, sellPrice, units, sellsTokens);
    }

    // Factory owner can withdraw any ERC20 asset tokens from this contract
    //
    // This method is included in the case where this contract receives
    // the wrong tokens
    //
    // The OwnerWithdrewERC20Token() event is logged with the following
    // parameter:
    //   tokenAddress  is the address of the tokens withdrawn by the maker
    //   tokens        is the number of tokens withdrawn by the maker
    function ownerWithdrawERC20Token(address tokenAddress, uint256 tokens) onlyOwner returns (bool ok) {
        OwnerWithdrewERC20Token(tokenAddress, tokens);
        return ERC20Partial(tokenAddress).transfer(owner, tokens);
    }

    // Prevents accidental sending of ether to the factory
    function () {
        throw;
    }
}

pragma solidity ^0.4.4;

// ------------------------------------------------------------------------
// TokenSellerFactory
//
// Decentralised trustless ERC20-partially-compliant token to ETH exchange
// contract on the Ethereum blockchain.
//
// This caters for the Golem Network Token which does not implement the
// ERC20 transferFrom(...), approve(...) and allowance(...) methods
//
// Enjoy. (c) JonnyLatte, Cintix & BokkyPooBah 2016. The MIT licence.
// ------------------------------------------------------------------------

// https://github.com/ethereum/EIPs/issues/20
contract ERC20Partial {
    function totalSupply() constant returns (uint totalSupply);
    function balanceOf(address _owner) constant returns (uint balance);
    function transfer(address _to, uint _value) returns (bool success);
    // function transferFrom(address _from, address _to, uint _value) returns (bool success);
    // function approve(address _spender, uint _value) returns (bool success);
    // function allowance(address _owner, address _spender) constant returns (uint remaining);
    event Transfer(address indexed _from, address indexed _to, uint _value);
    // event Approval(address indexed _owner, address indexed _spender, uint _value);
}

contract Owned {
    address public owner;
    event OwnershipTransferred(address indexed _from, address indexed _to);

    function Owned() {
        owner = msg.sender;
    }

    modifier onlyOwner {
        if (msg.sender != owner) throw;
        _;
    }

    function transferOwnership(address newOwner) onlyOwner {
        OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }
}

// contract can sell tokens for ETH
// prices are in amount of wei per batch of token units

contract TokenSeller is Owned {

    address public asset;       // address of token
    uint256 public sellPrice;   // contract sells lots of tokens at this price
    uint256 public units;       // lot size (token-wei)

    bool public sellsTokens;    // is contract selling

    event ActivatedEvent(bool sells);
    event MakerWithdrewAsset(uint256 tokens);
    event MakerWithdrewERC20Token(address tokenAddress, uint256 tokens);
    event MakerWithdrewEther(uint256 ethers);
    event TakerBoughtAsset(address indexed buyer, uint256 ethersSent,
        uint256 ethersReturned, uint256 tokensBought);

    // Constructor - only to be called by the TokenSellerFactory contract
    function TokenSeller (
        address _asset,
        uint256 _sellPrice,
        uint256 _units,
        bool    _sellsTokens
    ) internal {
        asset       = _asset;
        sellPrice   = _sellPrice;
        units       = _units;
        sellsTokens = _sellsTokens;
        ActivatedEvent(sellsTokens);
    }

    // Maker can activate or deactivate this contract's
    // selling status
    //
    // The ActivatedEvent() event is logged with the following
    // parameter:
    //   sellsTokens  this contract can sell asset tokens
    function activate (
        bool _sellsTokens
    ) onlyOwner {
        sellsTokens = _sellsTokens;
        ActivatedEvent(sellsTokens);
    }

    // Maker can withdraw asset tokens from this contract, with the
    // following parameter:
    //   tokens  is the number of asset tokens to be withdrawn
    //
    // The MakerWithdrewAsset() event is logged with the following
    // parameter:
    //   tokens  is the number of tokens withdrawn by the maker
    //
    // This method was called withdrawAsset() in the old version
    function makerWithdrawAsset(uint256 tokens) onlyOwner returns (bool ok) {
        MakerWithdrewAsset(tokens);
        return ERC20Partial(asset).transfer(owner, tokens);
    }

    // Maker can withdraw any ERC20 asset tokens from this contract
    //
    // This method is included in the case where this contract receives
    // the wrong tokens
    //
    // The MakerWithdrewERC20Token() event is logged with the following
    // parameter:
    //   tokenAddress  is the address of the tokens withdrawn by the maker
    //   tokens        is the number of tokens withdrawn by the maker
    //
    // This method was called withdrawToken() in the old version
    function makerWithdrawERC20Token(
        address tokenAddress,
        uint256 tokens
    ) onlyOwner returns (bool ok) {
        MakerWithdrewERC20Token(tokenAddress, tokens);
        return ERC20Partial(tokenAddress).transfer(owner, tokens);
    }

    // Maker withdraws ethers from this contract
    //
    // The MakerWithdrewEther() event is logged with the following parameter
    //   ethers  is the number of ethers withdrawn by the maker
    //
    // This method was called withdraw() in the old version
    function makerWithdrawEther(uint256 ethers) onlyOwner returns (bool ok) {
        if (this.balance >= ethers) {
            MakerWithdrewEther(ethers);
            return owner.send(ethers);
        }
    }

    // Taker buys asset tokens by sending ethers
    //
    // The TakerBoughtAsset() event is logged with the following parameters
    //   buyer           is the buyer's address
    //   ethersSent      is the number of ethers sent by the buyer
    //   ethersReturned  is the number of ethers sent back to the buyer as
    //                   change
    //   tokensBought    is the number of asset tokens sent to the buyer
    //
    // This method was called buy() in the old version
    function takerBuyAsset() payable {
        if (sellsTokens || msg.sender == owner) {
            uint order    = msg.value / sellPrice;
            uint can_sell = ERC20Partial(asset).balanceOf(address(this)) / units;
            uint256 change = 0;
            if (order > can_sell) {
                change = msg.value - (can_sell * sellPrice);
                order = can_sell;
                if (!msg.sender.send(change)) throw;
            }
            if (order > 0) {
                if(!ERC20Partial(asset).transfer(msg.sender, order * units)) throw;
            }
            TakerBoughtAsset(msg.sender, msg.value, order * units, change);
        }
        // Return user funds if the contract is not selling
        else if (!msg.sender.send(msg.value)) throw;
    }

    // Taker buys tokens by sending ethers
    function () payable {
        takerBuyAsset();
    }
}

// This contract deploys TokenSeller contracts and logs the event
contract TokenSellerFactory is Owned {

    event TradeListing(address ownerAddress, address tokenSellerAddress, address asset,
        uint256 sellPrice, uint256 units, bool sellsTokens);
    event OwnerWithdrewERC20Token(address tokenAddress, uint256 tokens);

    mapping(address => bool) _verify;

    // Anyone can call this method to verify the settings of a
    // TokenSeller contract. The parameters are:
    //   tradeContract  is the address of a TokenSeller contract
    //
    // Return values:
    //   valid        did this TokenTraderFactory create the TokenTrader contract?
    //   owner        is the owner of the TokenTrader contract
    //   asset        is the ERC20 asset address
    //   sellPrice    is the sell price in ethers per `units` of asset tokens
    //   units        is the number of units of asset tokens
    //   sellsTokens  is the TokenTrader contract selling tokens?
    //
    function verify(address tradeContract) constant returns (
        bool    valid,
        address owner,
        address asset,
        uint256 sellPrice,
        uint256 units,
        bool    sellsTokens
    ) {
        valid = _verify[tradeContract];
        if (valid) {
            TokenSeller t = TokenSeller(tradeContract);
            owner         = t.owner();
            asset         = t.asset();
            sellPrice     = t.sellPrice();
            units         = t.units();
            sellsTokens   = t.sellsTokens();
        }
    }

    // Maker can call this method to create a new TokenSeller contract
    // with the maker being the owner of this new contract
    //
    // Parameters:
    //   asset        is the ERC20 asset address
    //   sellPrice    is the sell price in ethers per `units` of asset tokens
    //   units        is the number of units of asset tokens
    //   sellsTokens  is the TokenSeller contract selling tokens?
    //
    // For example, listing a TokenSeller contract on the GNT Golem Network Token
    // where the contract will sell GNT tokens at a rate of 170/100000 = 0.0017 ETH
    // per GNT token:
    //   asset        0xa74476443119a942de498590fe1f2454d7d4ac0d
    //   sellPrice    170
    //   units        100000
    //   sellsTokens  true
    //
    // The TradeListing() event is logged with the following parameters
    //   ownerAddress        is the Maker's address
    //   tokenSellerAddress  is the address of the newly created TokenSeller contract
    //   asset               is the ERC20 asset address
    //   sellPrice           is the sell price in ethers per `units` of asset tokens
    //   unit                is the number of units of asset tokens
    //   sellsTokens         is the TokenSeller contract selling tokens?
    //
    // This method was called createTradeContract() in the old version
    //
    function createSaleContract(
        address asset,
        uint256 sellPrice,
        uint256 units,
        bool    sellsTokens
    ) returns (address seller) {
        // Cannot set negative price
        if (sellPrice < 0) throw;
        // Cannot sell zero or negative units
        if (units <= 0) throw;
        seller = new TokenSeller(
            asset,
            sellPrice,
            units,
            sellsTokens);
        // Record that this factory created the trader
        _verify[seller] = true;
        // Set the owner to whoever called the function
        TokenSeller(seller).transferOwnership(msg.sender);
        TradeListing(msg.sender, seller, asset, sellPrice, units, sellsTokens);
    }

    // Factory owner can withdraw any ERC20 asset tokens from this contract
    //
    // This method is included in the case where this contract receives
    // the wrong tokens
    //
    // The OwnerWithdrewERC20Token() event is logged with the following
    // parameter:
    //   tokenAddress  is the address of the tokens withdrawn by the maker
    //   tokens        is the number of tokens withdrawn by the maker
    function ownerWithdrawERC20Token(address tokenAddress, uint256 tokens) onlyOwner returns (bool ok) {
        OwnerWithdrewERC20Token(tokenAddress, tokens);
        return ERC20Partial(tokenAddress).transfer(owner, tokens);
    }

    // Prevents accidental sending of ether to the factory
    function () {
        throw;
    }
}