ETH Price: $2,089.79 (+1.81%)

Transaction Decoder

Block:
24435951 at Feb-11-2026 08:34:59 PM +UTC
Transaction Fee:
0.00099113872473799 ETH $2.07
Gas Used:
788,765 Gas / 1.256570366 Gwei

Emitted Events:

36 Factory.NewLiability( liability=0xecad903420ad49b5c4ec4cb7f32da4895c2e2627 )
37 Factory.HashConsumed( hash=73F7C2404631DDC975FA7A57B17EECB75FF8CEF4FFDE86699ADF0ED508ADD300 )
38 Factory.HashConsumed( hash=E33D758B42DF884F2551C84D8B05567D51F2F832CFC14CC907CD8625939A2091 )

Account State Difference:

  Address   Before After State Difference Code
0x04C672af...1d8EcbbeE
(quasarbuilder)
20.249548852974120199 Eth20.250318084632462004 Eth0.000769231658341805
0x6EFBA8fb...6a287C3Ad
3.185189257340755584 Eth
Nonce: 8489
3.184198118616017594 Eth
Nonce: 8490
0.00099113872473799
0x7e384AD1...273DC1225
0xecAd9034...95c2e2627
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 3782669853689538850459001210098890504365882523271628584051567792393820594317014269117422742721060703888570481401617405

Execution Trace

0x04c672af1e54d6c9bd3f153d590f5681d8ecbbee.d2b962f2( )
  • Lighthouse.createLiability( _demand=0x000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001A00000000000000000000000007DE91B204C1C737BCEE6F000AAA6569CF7061CB7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004C672AF1E54D6C9BD3F153D590F5681D8ECBBEE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174DE190000000000000000000000006EFBA8FB2AC5B6730729A972EC224426A287C3AD00000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000022ED186A3B677F48F31A812AC80451F769A6EE1968431989DF627B7A3C45D42DF96C7A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022F57DEB21D3FE56338A44648C26CEFF83E84FE826955381556945805E7A02E18EE4DA00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000411EC938A6E499B445172CBCABDA06E83D86EEF6FE679A9D01DA66095D1DC184324C8BC550068392B792333BBE9C455B34A3CC8C543B0AAC34E340025D0B7144AD1C00000000000000000000000000000000000000000000000000000000000000, _offer=0x000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001A00000000000000000000000007DE91B204C1C737BCEE6F000AAA6569CF7061CB70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004C672AF1E54D6C9BD3F153D590F5681D8ECBBEE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174DE190000000000000000000000006EFBA8FB2AC5B6730729A972EC224426A287C3AD00000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000022ED186A3B677F48F31A812AC80451F769A6EE1968431989DF627B7A3C45D42DF96C7A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022F57DEB21D3FE56338A44648C26CEFF83E84FE826955381556945805E7A02E18EE4DA0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041155EEC2B687EA147D50A51554267B3E1FC957C798090230345F7F4E0DC8F57412C3B49411DF3D9FB8A4A00E94189D870311CC850967543396250F7F68FF84F111C00000000000000000000000000000000000000000000000000000000000000 ) => ( True )
    • Factory.createLiability( _demand=0x000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001A00000000000000000000000007DE91B204C1C737BCEE6F000AAA6569CF7061CB7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004C672AF1E54D6C9BD3F153D590F5681D8ECBBEE00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174DE190000000000000000000000006EFBA8FB2AC5B6730729A972EC224426A287C3AD00000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000022ED186A3B677F48F31A812AC80451F769A6EE1968431989DF627B7A3C45D42DF96C7A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022F57DEB21D3FE56338A44648C26CEFF83E84FE826955381556945805E7A02E18EE4DA00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000411EC938A6E499B445172CBCABDA06E83D86EEF6FE679A9D01DA66095D1DC184324C8BC550068392B792333BBE9C455B34A3CC8C543B0AAC34E340025D0B7144AD1C00000000000000000000000000000000000000000000000000000000000000, _offer=0x000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001A00000000000000000000000007DE91B204C1C737BCEE6F000AAA6569CF7061CB70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004C672AF1E54D6C9BD3F153D590F5681D8ECBBEE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000174DE190000000000000000000000006EFBA8FB2AC5B6730729A972EC224426A287C3AD00000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000022ED186A3B677F48F31A812AC80451F769A6EE1968431989DF627B7A3C45D42DF96C7A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022F57DEB21D3FE56338A44648C26CEFF83E84FE826955381556945805E7A02E18EE4DA0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041155EEC2B687EA147D50A51554267B3E1FC957C798090230345F7F4E0DC8F57412C3B49411DF3D9FB8A4A00E94189D870311CC850967543396250F7F68FF84F111C00000000000000000000000000000000000000000000000000000000000000 ) => ( liability=0xecAd903420Ad49b5C4EC4CB7f32DA4895c2e2627 )
      • 0xecad903420ad49b5c4ec4cb7f32da4895c2e2627.60316000( )
      • 0xecad903420ad49b5c4ec4cb7f32da4895c2e2627.66d38203( )
        • Liability.setup( _xrt=0x7dE91B204C1C737bcEe6F000AAA6569Cf7061cb7 ) => ( True )
        • 0xecad903420ad49b5c4ec4cb7f32da4895c2e2627.48a984e4( )
          • Liability.demand( _model=0xED186A3B677F48F31A812AC80451F769A6EE1968431989DF627B7A3C45D42DF96C7A, _objective=0xF57DEB21D3FE56338A44648C26CEFF83E84FE826955381556945805E7A02E18EE4DA, _token=0x7dE91B204C1C737bcEe6F000AAA6569Cf7061cb7, _cost=0, _lighthouse=0x04C672af1e54d6C9Bd3f153d590f5681d8EcbbeE, _validator=0x0000000000000000000000000000000000000000, _validator_fee=0, _deadline=24436249, _sender=0x6EFBA8fb2AC5b6730729a972eC224426a287C3Ad, _signature=0x1EC938A6E499B445172CBCABDA06E83D86EEF6FE679A9D01DA66095D1DC184324C8BC550068392B792333BBE9C455B34A3CC8C543B0AAC34E340025D0B7144AD1C ) => ( True )
            • Factory.nonceOf( 0x6EFBA8fb2AC5b6730729a972eC224426a287C3Ad ) => ( 7460 )
            • Null: 0x000...001.359a53c3( )
            • 0xecad903420ad49b5c4ec4cb7f32da4895c2e2627.STATICCALL( )
              • Liability.DELEGATECALL( )
              • 0xecad903420ad49b5c4ec4cb7f32da4895c2e2627.STATICCALL( )
                • Liability.DELEGATECALL( )
                • 0xecad903420ad49b5c4ec4cb7f32da4895c2e2627.413781d2( )
                  • Liability.offer( _model=0xED186A3B677F48F31A812AC80451F769A6EE1968431989DF627B7A3C45D42DF96C7A, _objective=0xF57DEB21D3FE56338A44648C26CEFF83E84FE826955381556945805E7A02E18EE4DA, _token=0x7dE91B204C1C737bcEe6F000AAA6569Cf7061cb7, _cost=0, _validator=0x0000000000000000000000000000000000000000, _lighthouse=0x04C672af1e54d6C9Bd3f153d590f5681d8EcbbeE, _lighthouse_fee=0, _deadline=24436249, _sender=0x6EFBA8fb2AC5b6730729a972eC224426a287C3Ad, _signature=0x155EEC2B687EA147D50A51554267B3E1FC957C798090230345F7F4E0DC8F57412C3B49411DF3D9FB8A4A00E94189D870311CC850967543396250F7F68FF84F111C ) => ( True )
                    • Factory.nonceOf( 0x6EFBA8fb2AC5b6730729a972eC224426a287C3Ad ) => ( 7461 )
                    • Null: 0x000...001.b80543ee( )
                    • 0xecad903420ad49b5c4ec4cb7f32da4895c2e2627.STATICCALL( )
                      • Liability.DELEGATECALL( )
                      • 0xecad903420ad49b5c4ec4cb7f32da4895c2e2627.STATICCALL( )
                        • Liability.DELEGATECALL( )
                        • 0xecad903420ad49b5c4ec4cb7f32da4895c2e2627.STATICCALL( )
                          • Liability.DELEGATECALL( )
                          • 0xecad903420ad49b5c4ec4cb7f32da4895c2e2627.STATICCALL( )
                            • Liability.DELEGATECALL( )
                            • 0xecad903420ad49b5c4ec4cb7f32da4895c2e2627.STATICCALL( )
                              • Liability.DELEGATECALL( )
                              • 0xecad903420ad49b5c4ec4cb7f32da4895c2e2627.STATICCALL( )
                                • Liability.DELEGATECALL( )
                                • 0xecad903420ad49b5c4ec4cb7f32da4895c2e2627.STATICCALL( )
                                  • Liability.DELEGATECALL( )
                                  • Factory.liabilityCreated( _liability=0xecAd903420Ad49b5C4EC4CB7f32DA4895c2e2627, _gas=778401 ) => ( True )
                                    File 1 of 3: Factory
                                    // File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title ERC20 interface
                                     * @dev see https://github.com/ethereum/EIPs/issues/20
                                     */
                                    interface IERC20 {
                                        function transfer(address to, uint256 value) external returns (bool);
                                    
                                        function approve(address spender, uint256 value) external returns (bool);
                                    
                                        function transferFrom(address from, address to, uint256 value) external returns (bool);
                                    
                                        function totalSupply() external view returns (uint256);
                                    
                                        function balanceOf(address who) external view returns (uint256);
                                    
                                        function allowance(address owner, address spender) external view returns (uint256);
                                    
                                        event Transfer(address indexed from, address indexed to, uint256 value);
                                    
                                        event Approval(address indexed owner, address indexed spender, uint256 value);
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/math/SafeMath.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title SafeMath
                                     * @dev Unsigned math operations with safety checks that revert on error
                                     */
                                    library SafeMath {
                                        /**
                                        * @dev Multiplies two unsigned integers, reverts on overflow.
                                        */
                                        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                                            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                                            // benefit is lost if 'b' is also tested.
                                            // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                                            if (a == 0) {
                                                return 0;
                                            }
                                    
                                            uint256 c = a * b;
                                            require(c / a == b);
                                    
                                            return c;
                                        }
                                    
                                        /**
                                        * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
                                        */
                                        function div(uint256 a, uint256 b) internal pure returns (uint256) {
                                            // Solidity only automatically asserts when dividing by 0
                                            require(b > 0);
                                            uint256 c = a / b;
                                            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
                                    
                                            return c;
                                        }
                                    
                                        /**
                                        * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
                                        */
                                        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                                            require(b <= a);
                                            uint256 c = a - b;
                                    
                                            return c;
                                        }
                                    
                                        /**
                                        * @dev Adds two unsigned integers, reverts on overflow.
                                        */
                                        function add(uint256 a, uint256 b) internal pure returns (uint256) {
                                            uint256 c = a + b;
                                            require(c >= a);
                                    
                                            return c;
                                        }
                                    
                                        /**
                                        * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
                                        * reverts when dividing by zero.
                                        */
                                        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                                            require(b != 0);
                                            return a % b;
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    /**
                                     * @title SafeERC20
                                     * @dev Wrappers around ERC20 operations that throw on failure.
                                     * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
                                     * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
                                     */
                                    library SafeERC20 {
                                        using SafeMath for uint256;
                                    
                                        function safeTransfer(IERC20 token, address to, uint256 value) internal {
                                            require(token.transfer(to, value));
                                        }
                                    
                                        function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
                                            require(token.transferFrom(from, to, value));
                                        }
                                    
                                        function safeApprove(IERC20 token, address spender, uint256 value) internal {
                                            // safeApprove should only be called when setting an initial allowance,
                                            // or when resetting it to zero. To increase and decrease it, use
                                            // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
                                            require((value == 0) || (token.allowance(address(this), spender) == 0));
                                            require(token.approve(spender, value));
                                        }
                                    
                                        function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
                                            uint256 newAllowance = token.allowance(address(this), spender).add(value);
                                            require(token.approve(spender, newAllowance));
                                        }
                                    
                                        function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
                                            uint256 newAllowance = token.allowance(address(this), spender).sub(value);
                                            require(token.approve(spender, newAllowance));
                                        }
                                    }
                                    
                                    // File: contracts/ens/AbstractENS.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    contract AbstractENS {
                                        function owner(bytes32 _node) public view returns(address);
                                        function resolver(bytes32 _node) public view returns(address);
                                        function ttl(bytes32 _node) public view returns(uint64);
                                        function setOwner(bytes32 _node, address _owner) public;
                                        function setSubnodeOwner(bytes32 _node, bytes32 _label, address _owner) public;
                                        function setResolver(bytes32 _node, address _resolver) public;
                                        function setTTL(bytes32 _node, uint64 _ttl) public;
                                    
                                        // Logged when the owner of a node assigns a new owner to a subnode.
                                        event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
                                    
                                        // Logged when the owner of a node transfers ownership to a new account.
                                        event Transfer(bytes32 indexed node, address owner);
                                    
                                        // Logged when the resolver for a node changes.
                                        event NewResolver(bytes32 indexed node, address resolver);
                                    
                                        // Logged when the TTL of a node changes
                                        event NewTTL(bytes32 indexed node, uint64 ttl);
                                    }
                                    
                                    // File: contracts/ens/AbstractResolver.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    contract AbstractResolver {
                                        function supportsInterface(bytes4 _interfaceID) public view returns (bool);
                                        function addr(bytes32 _node) public view returns (address ret);
                                        function setAddr(bytes32 _node, address _addr) public;
                                        function hash(bytes32 _node) public view returns (bytes32 ret);
                                        function setHash(bytes32 _node, bytes32 _hash) public;
                                    }
                                    
                                    // File: contracts/misc/SingletonHash.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    contract SingletonHash {
                                        event HashConsumed(bytes32 indexed hash);
                                    
                                        /**
                                         * @dev Used hash accounting
                                         */
                                        mapping(bytes32 => bool) public isHashConsumed;
                                    
                                        /**
                                         * @dev Parameter can be used only once
                                         * @param _hash Single usage hash
                                         */
                                        function singletonHash(bytes32 _hash) internal {
                                            require(!isHashConsumed[_hash]);
                                            isHashConsumed[_hash] = true;
                                            emit HashConsumed(_hash);
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/access/Roles.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title Roles
                                     * @dev Library for managing addresses assigned to a Role.
                                     */
                                    library Roles {
                                        struct Role {
                                            mapping (address => bool) bearer;
                                        }
                                    
                                        /**
                                         * @dev give an account access to this role
                                         */
                                        function add(Role storage role, address account) internal {
                                            require(account != address(0));
                                            require(!has(role, account));
                                    
                                            role.bearer[account] = true;
                                        }
                                    
                                        /**
                                         * @dev remove an account's access to this role
                                         */
                                        function remove(Role storage role, address account) internal {
                                            require(account != address(0));
                                            require(has(role, account));
                                    
                                            role.bearer[account] = false;
                                        }
                                    
                                        /**
                                         * @dev check if an account has this role
                                         * @return bool
                                         */
                                        function has(Role storage role, address account) internal view returns (bool) {
                                            require(account != address(0));
                                            return role.bearer[account];
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/access/roles/SignerRole.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    contract SignerRole {
                                        using Roles for Roles.Role;
                                    
                                        event SignerAdded(address indexed account);
                                        event SignerRemoved(address indexed account);
                                    
                                        Roles.Role private _signers;
                                    
                                        constructor () internal {
                                            _addSigner(msg.sender);
                                        }
                                    
                                        modifier onlySigner() {
                                            require(isSigner(msg.sender));
                                            _;
                                        }
                                    
                                        function isSigner(address account) public view returns (bool) {
                                            return _signers.has(account);
                                        }
                                    
                                        function addSigner(address account) public onlySigner {
                                            _addSigner(account);
                                        }
                                    
                                        function renounceSigner() public {
                                            _removeSigner(msg.sender);
                                        }
                                    
                                        function _addSigner(address account) internal {
                                            _signers.add(account);
                                            emit SignerAdded(account);
                                        }
                                    
                                        function _removeSigner(address account) internal {
                                            _signers.remove(account);
                                            emit SignerRemoved(account);
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/cryptography/ECDSA.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title Elliptic curve signature operations
                                     * @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
                                     * TODO Remove this library once solidity supports passing a signature to ecrecover.
                                     * See https://github.com/ethereum/solidity/issues/864
                                     */
                                    
                                    library ECDSA {
                                        /**
                                         * @dev Recover signer address from a message by using their signature
                                         * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
                                         * @param signature bytes signature, the signature is generated using web3.eth.sign()
                                         */
                                        function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
                                            bytes32 r;
                                            bytes32 s;
                                            uint8 v;
                                    
                                            // Check the signature length
                                            if (signature.length != 65) {
                                                return (address(0));
                                            }
                                    
                                            // Divide the signature in r, s and v variables
                                            // ecrecover takes the signature parameters, and the only way to get them
                                            // currently is to use assembly.
                                            // solhint-disable-next-line no-inline-assembly
                                            assembly {
                                                r := mload(add(signature, 0x20))
                                                s := mload(add(signature, 0x40))
                                                v := byte(0, mload(add(signature, 0x60)))
                                            }
                                    
                                            // Version of signature should be 27 or 28, but 0 and 1 are also possible versions
                                            if (v < 27) {
                                                v += 27;
                                            }
                                    
                                            // If the version is correct return the signer address
                                            if (v != 27 && v != 28) {
                                                return (address(0));
                                            } else {
                                                return ecrecover(hash, v, r, s);
                                            }
                                        }
                                    
                                        /**
                                         * toEthSignedMessageHash
                                         * @dev prefix a bytes32 value with "\x19Ethereum Signed Message:"
                                         * and hash the result
                                         */
                                        function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
                                            // 32 is the length in bytes of hash,
                                            // enforced by the type signature above
                                            return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/drafts/SignatureBouncer.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    /**
                                     * @title SignatureBouncer
                                     * @author PhABC, Shrugs and aflesher
                                     * @dev SignatureBouncer allows users to submit a signature as a permission to
                                     * do an action.
                                     * If the signature is from one of the authorized signer addresses, the
                                     * signature is valid.
                                     * Note that SignatureBouncer offers no protection against replay attacks, users
                                     * must add this themselves!
                                     *
                                     * Signer addresses can be individual servers signing grants or different
                                     * users within a decentralized club that have permission to invite other
                                     * members. This technique is useful for whitelists and airdrops; instead of
                                     * putting all valid addresses on-chain, simply sign a grant of the form
                                     * keccak256(abi.encodePacked(`:contractAddress` + `:granteeAddress`)) using a
                                     * valid signer address.
                                     * Then restrict access to your crowdsale/whitelist/airdrop using the
                                     * `onlyValidSignature` modifier (or implement your own using _isValidSignature).
                                     * In addition to `onlyValidSignature`, `onlyValidSignatureAndMethod` and
                                     * `onlyValidSignatureAndData` can be used to restrict access to only a given
                                     * method or a given method with given parameters respectively.
                                     * See the tests in SignatureBouncer.test.js for specific usage examples.
                                     *
                                     * @notice A method that uses the `onlyValidSignatureAndData` modifier must make
                                     * the _signature parameter the "last" parameter. You cannot sign a message that
                                     * has its own signature in it so the last 128 bytes of msg.data (which
                                     * represents the length of the _signature data and the _signaature data itself)
                                     * is ignored when validating. Also non fixed sized parameters make constructing
                                     * the data in the signature much more complex.
                                     * See https://ethereum.stackexchange.com/a/50616 for more details.
                                     */
                                    contract SignatureBouncer is SignerRole {
                                        using ECDSA for bytes32;
                                    
                                        // Function selectors are 4 bytes long, as documented in
                                        // https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector
                                        uint256 private constant _METHOD_ID_SIZE = 4;
                                        // Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes
                                        uint256 private constant _SIGNATURE_SIZE = 96;
                                    
                                        constructor () internal {
                                            // solhint-disable-previous-line no-empty-blocks
                                        }
                                    
                                        /**
                                         * @dev requires that a valid signature of a signer was provided
                                         */
                                        modifier onlyValidSignature(bytes memory signature) {
                                            require(_isValidSignature(msg.sender, signature));
                                            _;
                                        }
                                    
                                        /**
                                         * @dev requires that a valid signature with a specifed method of a signer was provided
                                         */
                                        modifier onlyValidSignatureAndMethod(bytes memory signature) {
                                            require(_isValidSignatureAndMethod(msg.sender, signature));
                                            _;
                                        }
                                    
                                        /**
                                         * @dev requires that a valid signature with a specifed method and params of a signer was provided
                                         */
                                        modifier onlyValidSignatureAndData(bytes memory signature) {
                                            require(_isValidSignatureAndData(msg.sender, signature));
                                            _;
                                        }
                                    
                                        /**
                                         * @dev is the signature of `this + sender` from a signer?
                                         * @return bool
                                         */
                                        function _isValidSignature(address account, bytes memory signature) internal view returns (bool) {
                                            return _isValidDataHash(keccak256(abi.encodePacked(address(this), account)), signature);
                                        }
                                    
                                        /**
                                         * @dev is the signature of `this + sender + methodId` from a signer?
                                         * @return bool
                                         */
                                        function _isValidSignatureAndMethod(address account, bytes memory signature) internal view returns (bool) {
                                            bytes memory data = new bytes(_METHOD_ID_SIZE);
                                            for (uint i = 0; i < data.length; i++) {
                                                data[i] = msg.data[i];
                                            }
                                            return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature);
                                        }
                                    
                                        /**
                                            * @dev is the signature of `this + sender + methodId + params(s)` from a signer?
                                            * @notice the signature parameter of the method being validated must be the "last" parameter
                                            * @return bool
                                            */
                                        function _isValidSignatureAndData(address account, bytes memory signature) internal view returns (bool) {
                                            require(msg.data.length > _SIGNATURE_SIZE);
                                    
                                            bytes memory data = new bytes(msg.data.length - _SIGNATURE_SIZE);
                                            for (uint i = 0; i < data.length; i++) {
                                                data[i] = msg.data[i];
                                            }
                                    
                                            return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature);
                                        }
                                    
                                        /**
                                         * @dev internal function to convert a hash to an eth signed message
                                         * and then recover the signature and check it against the signer role
                                         * @return bool
                                         */
                                        function _isValidDataHash(bytes32 hash, bytes memory signature) internal view returns (bool) {
                                            address signer = hash.toEthSignedMessageHash().recover(signature);
                                    
                                            return signer != address(0) && isSigner(signer);
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    /**
                                     * @title Standard ERC20 token
                                     *
                                     * @dev Implementation of the basic standard token.
                                     * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
                                     * Originally based on code by FirstBlood:
                                     * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
                                     *
                                     * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for
                                     * all accounts just by listening to said events. Note that this isn't required by the specification, and other
                                     * compliant implementations may not do it.
                                     */
                                    contract ERC20 is IERC20 {
                                        using SafeMath for uint256;
                                    
                                        mapping (address => uint256) private _balances;
                                    
                                        mapping (address => mapping (address => uint256)) private _allowed;
                                    
                                        uint256 private _totalSupply;
                                    
                                        /**
                                        * @dev Total number of tokens in existence
                                        */
                                        function totalSupply() public view returns (uint256) {
                                            return _totalSupply;
                                        }
                                    
                                        /**
                                        * @dev Gets the balance of the specified address.
                                        * @param owner The address to query the balance of.
                                        * @return An uint256 representing the amount owned by the passed address.
                                        */
                                        function balanceOf(address owner) public view returns (uint256) {
                                            return _balances[owner];
                                        }
                                    
                                        /**
                                         * @dev Function to check the amount of tokens that an owner allowed to a spender.
                                         * @param owner address The address which owns the funds.
                                         * @param spender address The address which will spend the funds.
                                         * @return A uint256 specifying the amount of tokens still available for the spender.
                                         */
                                        function allowance(address owner, address spender) public view returns (uint256) {
                                            return _allowed[owner][spender];
                                        }
                                    
                                        /**
                                        * @dev Transfer token for a specified address
                                        * @param to The address to transfer to.
                                        * @param value The amount to be transferred.
                                        */
                                        function transfer(address to, uint256 value) public returns (bool) {
                                            _transfer(msg.sender, to, value);
                                            return true;
                                        }
                                    
                                        /**
                                         * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
                                         * Beware that changing an allowance with this method brings the risk that someone may use both the old
                                         * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
                                         * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
                                         * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
                                         * @param spender The address which will spend the funds.
                                         * @param value The amount of tokens to be spent.
                                         */
                                        function approve(address spender, uint256 value) public returns (bool) {
                                            require(spender != address(0));
                                    
                                            _allowed[msg.sender][spender] = value;
                                            emit Approval(msg.sender, spender, value);
                                            return true;
                                        }
                                    
                                        /**
                                         * @dev Transfer tokens from one address to another.
                                         * Note that while this function emits an Approval event, this is not required as per the specification,
                                         * and other compliant implementations may not emit the event.
                                         * @param from address The address which you want to send tokens from
                                         * @param to address The address which you want to transfer to
                                         * @param value uint256 the amount of tokens to be transferred
                                         */
                                        function transferFrom(address from, address to, uint256 value) public returns (bool) {
                                            _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
                                            _transfer(from, to, value);
                                            emit Approval(from, msg.sender, _allowed[from][msg.sender]);
                                            return true;
                                        }
                                    
                                        /**
                                         * @dev Increase the amount of tokens that an owner allowed to a spender.
                                         * approve should be called when allowed_[_spender] == 0. To increment
                                         * allowed value is better to use this function to avoid 2 calls (and wait until
                                         * the first transaction is mined)
                                         * From MonolithDAO Token.sol
                                         * Emits an Approval event.
                                         * @param spender The address which will spend the funds.
                                         * @param addedValue The amount of tokens to increase the allowance by.
                                         */
                                        function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
                                            require(spender != address(0));
                                    
                                            _allowed[msg.sender][spender] = _allowed[msg.sender][spender].add(addedValue);
                                            emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
                                            return true;
                                        }
                                    
                                        /**
                                         * @dev Decrease the amount of tokens that an owner allowed to a spender.
                                         * approve should be called when allowed_[_spender] == 0. To decrement
                                         * allowed value is better to use this function to avoid 2 calls (and wait until
                                         * the first transaction is mined)
                                         * From MonolithDAO Token.sol
                                         * Emits an Approval event.
                                         * @param spender The address which will spend the funds.
                                         * @param subtractedValue The amount of tokens to decrease the allowance by.
                                         */
                                        function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
                                            require(spender != address(0));
                                    
                                            _allowed[msg.sender][spender] = _allowed[msg.sender][spender].sub(subtractedValue);
                                            emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
                                            return true;
                                        }
                                    
                                        /**
                                        * @dev Transfer token for a specified addresses
                                        * @param from The address to transfer from.
                                        * @param to The address to transfer to.
                                        * @param value The amount to be transferred.
                                        */
                                        function _transfer(address from, address to, uint256 value) internal {
                                            require(to != address(0));
                                    
                                            _balances[from] = _balances[from].sub(value);
                                            _balances[to] = _balances[to].add(value);
                                            emit Transfer(from, to, value);
                                        }
                                    
                                        /**
                                         * @dev Internal function that mints an amount of the token and assigns it to
                                         * an account. This encapsulates the modification of balances such that the
                                         * proper events are emitted.
                                         * @param account The account that will receive the created tokens.
                                         * @param value The amount that will be created.
                                         */
                                        function _mint(address account, uint256 value) internal {
                                            require(account != address(0));
                                    
                                            _totalSupply = _totalSupply.add(value);
                                            _balances[account] = _balances[account].add(value);
                                            emit Transfer(address(0), account, value);
                                        }
                                    
                                        /**
                                         * @dev Internal function that burns an amount of the token of a given
                                         * account.
                                         * @param account The account whose tokens will be burnt.
                                         * @param value The amount that will be burnt.
                                         */
                                        function _burn(address account, uint256 value) internal {
                                            require(account != address(0));
                                    
                                            _totalSupply = _totalSupply.sub(value);
                                            _balances[account] = _balances[account].sub(value);
                                            emit Transfer(account, address(0), value);
                                        }
                                    
                                        /**
                                         * @dev Internal function that burns an amount of the token of a given
                                         * account, deducting from the sender's allowance for said account. Uses the
                                         * internal burn function.
                                         * Emits an Approval event (reflecting the reduced allowance).
                                         * @param account The account whose tokens will be burnt.
                                         * @param value The amount that will be burnt.
                                         */
                                        function _burnFrom(address account, uint256 value) internal {
                                            _allowed[account][msg.sender] = _allowed[account][msg.sender].sub(value);
                                            _burn(account, value);
                                            emit Approval(account, msg.sender, _allowed[account][msg.sender]);
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    /**
                                     * @title Burnable Token
                                     * @dev Token that can be irreversibly burned (destroyed).
                                     */
                                    contract ERC20Burnable is ERC20 {
                                        /**
                                         * @dev Burns a specific amount of tokens.
                                         * @param value The amount of token to be burned.
                                         */
                                        function burn(uint256 value) public {
                                            _burn(msg.sender, value);
                                        }
                                    
                                        /**
                                         * @dev Burns a specific amount of tokens from the target address and decrements allowance
                                         * @param from address The address which you want to send tokens from
                                         * @param value uint256 The amount of token to be burned
                                         */
                                        function burnFrom(address from, uint256 value) public {
                                            _burnFrom(from, value);
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title Ownable
                                     * @dev The Ownable contract has an owner address, and provides basic authorization control
                                     * functions, this simplifies the implementation of "user permissions".
                                     */
                                    contract Ownable {
                                        address private _owner;
                                    
                                        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
                                    
                                        /**
                                         * @dev The Ownable constructor sets the original `owner` of the contract to the sender
                                         * account.
                                         */
                                        constructor () internal {
                                            _owner = msg.sender;
                                            emit OwnershipTransferred(address(0), _owner);
                                        }
                                    
                                        /**
                                         * @return the address of the owner.
                                         */
                                        function owner() public view returns (address) {
                                            return _owner;
                                        }
                                    
                                        /**
                                         * @dev Throws if called by any account other than the owner.
                                         */
                                        modifier onlyOwner() {
                                            require(isOwner());
                                            _;
                                        }
                                    
                                        /**
                                         * @return true if `msg.sender` is the owner of the contract.
                                         */
                                        function isOwner() public view returns (bool) {
                                            return msg.sender == _owner;
                                        }
                                    
                                        /**
                                         * @dev Allows the current owner to relinquish control of the contract.
                                         * @notice Renouncing to ownership will leave the contract without an owner.
                                         * It will not be possible to call the functions with the `onlyOwner`
                                         * modifier anymore.
                                         */
                                        function renounceOwnership() public onlyOwner {
                                            emit OwnershipTransferred(_owner, address(0));
                                            _owner = address(0);
                                        }
                                    
                                        /**
                                         * @dev Allows the current owner to transfer control of the contract to a newOwner.
                                         * @param newOwner The address to transfer ownership to.
                                         */
                                        function transferOwnership(address newOwner) public onlyOwner {
                                            _transferOwnership(newOwner);
                                        }
                                    
                                        /**
                                         * @dev Transfers control of the contract to a newOwner.
                                         * @param newOwner The address to transfer ownership to.
                                         */
                                        function _transferOwnership(address newOwner) internal {
                                            require(newOwner != address(0));
                                            emit OwnershipTransferred(_owner, newOwner);
                                            _owner = newOwner;
                                        }
                                    }
                                    
                                    // File: contracts/misc/DutchAuction.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    
                                    
                                    
                                    /// @title Dutch auction contract - distribution of XRT tokens using an auction.
                                    /// @author Stefan George - <[email protected]>
                                    /// @author Airalab - <[email protected]> 
                                    contract DutchAuction is SignatureBouncer, Ownable {
                                        using SafeERC20 for ERC20Burnable;
                                    
                                        /*
                                         *  Events
                                         */
                                        event BidSubmission(address indexed sender, uint256 amount);
                                    
                                        /*
                                         *  Constants
                                         */
                                        uint constant public WAITING_PERIOD = 0; // 1 days;
                                    
                                        /*
                                         *  Storage
                                         */
                                        ERC20Burnable public token;
                                        address public ambix;
                                        address payable public wallet;
                                        uint public maxTokenSold;
                                        uint public ceiling;
                                        uint public priceFactor;
                                        uint public startBlock;
                                        uint public endTime;
                                        uint public totalReceived;
                                        uint public finalPrice;
                                        mapping (address => uint) public bids;
                                        Stages public stage;
                                    
                                        /*
                                         *  Enums
                                         */
                                        enum Stages {
                                            AuctionDeployed,
                                            AuctionSetUp,
                                            AuctionStarted,
                                            AuctionEnded,
                                            TradingStarted
                                        }
                                    
                                        /*
                                         *  Modifiers
                                         */
                                        modifier atStage(Stages _stage) {
                                            // Contract on stage
                                            require(stage == _stage);
                                            _;
                                        }
                                    
                                        modifier isValidPayload() {
                                            require(msg.data.length == 4 || msg.data.length == 164);
                                            _;
                                        }
                                    
                                        modifier timedTransitions() {
                                            if (stage == Stages.AuctionStarted && calcTokenPrice() <= calcStopPrice())
                                                finalizeAuction();
                                            if (stage == Stages.AuctionEnded && now > endTime + WAITING_PERIOD)
                                                stage = Stages.TradingStarted;
                                            _;
                                        }
                                    
                                        /*
                                         *  Public functions
                                         */
                                        /// @dev Contract constructor function sets owner.
                                        /// @param _wallet Multisig wallet.
                                        /// @param _maxTokenSold Auction token balance.
                                        /// @param _ceiling Auction ceiling.
                                        /// @param _priceFactor Auction price factor.
                                        constructor(address payable _wallet, uint _maxTokenSold, uint _ceiling, uint _priceFactor)
                                            public
                                        {
                                            require(_wallet != address(0) && _ceiling > 0 && _priceFactor > 0);
                                    
                                            wallet = _wallet;
                                            maxTokenSold = _maxTokenSold;
                                            ceiling = _ceiling;
                                            priceFactor = _priceFactor;
                                            stage = Stages.AuctionDeployed;
                                        }
                                    
                                        /// @dev Setup function sets external contracts' addresses.
                                        /// @param _token Token address.
                                        /// @param _ambix Distillation cube address.
                                        function setup(ERC20Burnable _token, address _ambix)
                                            public
                                            onlyOwner
                                            atStage(Stages.AuctionDeployed)
                                        {
                                            // Validate argument
                                            require(_token != ERC20Burnable(0) && _ambix != address(0));
                                    
                                            token = _token;
                                            ambix = _ambix;
                                    
                                            // Validate token balance
                                            require(token.balanceOf(address(this)) == maxTokenSold);
                                    
                                            stage = Stages.AuctionSetUp;
                                        }
                                    
                                        /// @dev Starts auction and sets startBlock.
                                        function startAuction()
                                            public
                                            onlyOwner
                                            atStage(Stages.AuctionSetUp)
                                        {
                                            stage = Stages.AuctionStarted;
                                            startBlock = block.number;
                                        }
                                    
                                        /// @dev Calculates current token price.
                                        /// @return Returns token price.
                                        function calcCurrentTokenPrice()
                                            public
                                            timedTransitions
                                            returns (uint)
                                        {
                                            if (stage == Stages.AuctionEnded || stage == Stages.TradingStarted)
                                                return finalPrice;
                                            return calcTokenPrice();
                                        }
                                    
                                        /// @dev Returns correct stage, even if a function with timedTransitions modifier has not yet been called yet.
                                        /// @return Returns current auction stage.
                                        function updateStage()
                                            public
                                            timedTransitions
                                            returns (Stages)
                                        {
                                            return stage;
                                        }
                                    
                                        /// @dev Allows to send a bid to the auction.
                                        /// @param signature KYC approvement
                                        function bid(bytes calldata signature)
                                            external
                                            payable
                                            isValidPayload
                                            timedTransitions
                                            atStage(Stages.AuctionStarted)
                                            onlyValidSignature(signature)
                                            returns (uint amount)
                                        {
                                            require(msg.value > 0);
                                            amount = msg.value;
                                    
                                            address payable receiver = msg.sender;
                                    
                                            // Prevent that more than 90% of tokens are sold. Only relevant if cap not reached.
                                            uint maxWei = maxTokenSold * calcTokenPrice() / 10**9 - totalReceived;
                                            uint maxWeiBasedOnTotalReceived = ceiling - totalReceived;
                                            if (maxWeiBasedOnTotalReceived < maxWei)
                                                maxWei = maxWeiBasedOnTotalReceived;
                                    
                                            // Only invest maximum possible amount.
                                            if (amount > maxWei) {
                                                amount = maxWei;
                                                // Send change back to receiver address.
                                                receiver.transfer(msg.value - amount);
                                            }
                                    
                                            // Forward funding to ether wallet
                                            (bool success,) = wallet.call.value(amount)("");
                                            require(success);
                                    
                                            bids[receiver] += amount;
                                            totalReceived += amount;
                                            emit BidSubmission(receiver, amount);
                                    
                                            // Finalize auction when maxWei reached
                                            if (amount == maxWei)
                                                finalizeAuction();
                                        }
                                    
                                        /// @dev Claims tokens for bidder after auction.
                                        function claimTokens()
                                            public
                                            isValidPayload
                                            timedTransitions
                                            atStage(Stages.TradingStarted)
                                        {
                                            address receiver = msg.sender;
                                            uint tokenCount = bids[receiver] * 10**9 / finalPrice;
                                            bids[receiver] = 0;
                                            token.safeTransfer(receiver, tokenCount);
                                        }
                                    
                                        /// @dev Calculates stop price.
                                        /// @return Returns stop price.
                                        function calcStopPrice()
                                            view
                                            public
                                            returns (uint)
                                        {
                                            return totalReceived * 10**9 / maxTokenSold + 1;
                                        }
                                    
                                        /// @dev Calculates token price.
                                        /// @return Returns token price.
                                        function calcTokenPrice()
                                            view
                                            public
                                            returns (uint)
                                        {
                                            return priceFactor * 10**18 / (block.number - startBlock + 7500) + 1;
                                        }
                                    
                                        /*
                                         *  Private functions
                                         */
                                        function finalizeAuction()
                                            private
                                        {
                                            stage = Stages.AuctionEnded;
                                            finalPrice = totalReceived == ceiling ? calcTokenPrice() : calcStopPrice();
                                            uint soldTokens = totalReceived * 10**9 / finalPrice;
                                    
                                            if (totalReceived == ceiling) {
                                                // Auction contract transfers all unsold tokens to Ambix contract
                                                token.safeTransfer(ambix, maxTokenSold - soldTokens);
                                            } else {
                                                // Auction contract burn all unsold tokens
                                                token.burn(maxTokenSold - soldTokens);
                                            }
                                    
                                            endTime = now;
                                        }
                                    }
                                    
                                    // File: contracts/misc/SharedCode.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    // Inspired by https://github.com/GNSPS/2DProxy
                                    library SharedCode {
                                        /**
                                         * @dev Create tiny proxy without constructor
                                         * @param _shared Shared code contract address
                                         */
                                        function proxy(address _shared) internal returns (address instance) {
                                            bytes memory code = abi.encodePacked(
                                                hex"603160008181600b9039f3600080808080368092803773",
                                                _shared, hex"5af43d828181803e808314603057f35bfd"
                                            );
                                            assembly {
                                                instance := create(0, add(code, 0x20), 60)
                                                if iszero(extcodesize(instance)) {
                                                    revert(0, 0)
                                                }
                                            }
                                        }
                                    }
                                    
                                    // File: contracts/robonomics/interface/ILiability.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title Standard liability smart contract interface
                                     */
                                    contract ILiability {
                                        /**
                                         * @dev Liability termination signal
                                         */
                                        event Finalized(bool indexed success, bytes result);
                                    
                                        /**
                                         * @dev Behaviour model multihash
                                         */
                                        bytes public model;
                                    
                                        /**
                                         * @dev Objective ROSBAG multihash
                                         * @notice ROSBAGv2 is used: http://wiki.ros.org/Bags/Format/2.0 
                                         */
                                        bytes public objective;
                                    
                                        /**
                                         * @dev Report ROSBAG multihash 
                                         * @notice ROSBAGv2 is used: http://wiki.ros.org/Bags/Format/2.0 
                                         */
                                        bytes public result;
                                    
                                        /**
                                         * @dev Payment token address
                                         */
                                        address public token;
                                    
                                        /**
                                         * @dev Liability cost
                                         */
                                        uint256 public cost;
                                    
                                        /**
                                         * @dev Lighthouse fee in wn
                                         */
                                        uint256 public lighthouseFee;
                                    
                                        /**
                                         * @dev Validator fee in wn
                                         */
                                        uint256 public validatorFee;
                                    
                                        /**
                                         * @dev Robonomics demand message hash
                                         */
                                        bytes32 public demandHash;
                                    
                                        /**
                                         * @dev Robonomics offer message hash
                                         */
                                        bytes32 public offerHash;
                                    
                                        /**
                                         * @dev Liability promisor address
                                         */
                                        address public promisor;
                                    
                                        /**
                                         * @dev Liability promisee address
                                         */
                                        address public promisee;
                                    
                                        /**
                                         * @dev Lighthouse assigned to this liability
                                         */
                                        address public lighthouse;
                                    
                                        /**
                                         * @dev Liability validator address
                                         */
                                        address public validator;
                                    
                                        /**
                                         * @dev Liability success flag
                                         */
                                        bool public isSuccess;
                                    
                                        /**
                                         * @dev Liability finalization status flag
                                         */
                                        bool public isFinalized;
                                    
                                        /**
                                         * @dev Deserialize robonomics demand message
                                         * @notice It can be called by factory only
                                         */
                                        function demand(
                                            bytes   calldata _model,
                                            bytes   calldata _objective,
                                    
                                            address _token,
                                            uint256 _cost,
                                    
                                            address _lighthouse,
                                    
                                            address _validator,
                                            uint256 _validator_fee,
                                    
                                            uint256 _deadline,
                                            address _sender,
                                            bytes   calldata _signature
                                        ) external returns (bool);
                                    
                                        /**
                                         * @dev Deserialize robonomics offer message
                                         * @notice It can be called by factory only
                                         */
                                        function offer(
                                            bytes   calldata _model,
                                            bytes   calldata _objective,
                                            
                                            address _token,
                                            uint256 _cost,
                                    
                                            address _validator,
                                    
                                            address _lighthouse,
                                            uint256 _lighthouse_fee,
                                    
                                            uint256 _deadline,
                                            address _sender,
                                            bytes   calldata _signature
                                        ) external returns (bool);
                                    
                                        /**
                                         * @dev Finalize liability contract
                                         * @param _result Result data hash
                                         * @param _success Set 'true' when liability has success result
                                         * @param _signature Result signature: liability address, result and success flag signed by promisor
                                         * @notice It can be called by assigned lighthouse only
                                         */
                                        function finalize(
                                            bytes calldata _result,
                                            bool  _success,
                                            bytes calldata _signature
                                        ) external returns (bool);
                                    }
                                    
                                    // File: contracts/robonomics/interface/ILighthouse.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title Robonomics lighthouse contract interface
                                     */
                                    contract ILighthouse {
                                        /**
                                         * @dev Provider going online
                                         */
                                        event Online(address indexed provider);
                                    
                                        /**
                                         * @dev Provider going offline
                                         */
                                        event Offline(address indexed provider);
                                    
                                        /**
                                         * @dev Active robonomics provider
                                         */
                                        event Current(address indexed provider, uint256 indexed quota);
                                    
                                        /**
                                         * @dev Robonomics providers list
                                         */
                                        address[] public providers;
                                    
                                        /**
                                         * @dev Count of robonomics providers on this lighthouse
                                         */
                                        function providersLength() public view returns (uint256)
                                        { return providers.length; }
                                    
                                        /**
                                         * @dev Provider stake distribution
                                         */
                                        mapping(address => uint256) public stakes;
                                    
                                        /**
                                         * @dev Minimal stake to get one quota
                                         */
                                        uint256 public minimalStake;
                                    
                                        /**
                                         * @dev Silence timeout for provider in blocks
                                         */
                                        uint256 public timeoutInBlocks;
                                    
                                        /**
                                         * @dev Block number of last transaction from current provider
                                         */
                                        uint256 public keepAliveBlock;
                                    
                                        /**
                                         * @dev Round robin provider list marker
                                         */
                                        uint256 public marker;
                                    
                                        /**
                                         * @dev Current provider quota
                                         */
                                        uint256 public quota;
                                    
                                        /**
                                         * @dev Get quota of provider
                                         */
                                        function quotaOf(address _provider) public view returns (uint256)
                                        { return stakes[_provider] / minimalStake; }
                                    
                                        /**
                                         * @dev Increase stake and get more quota,
                                         *      one quota - one transaction in round
                                         * @param _value in wn
                                         * @notice XRT should be approved before call this 
                                         */
                                        function refill(uint256 _value) external returns (bool);
                                    
                                        /**
                                         * @dev Decrease stake and get XRT back
                                         * @param _value in wn
                                         */
                                        function withdraw(uint256 _value) external returns (bool);
                                    
                                        /**
                                         * @dev Create liability smart contract assigned to this lighthouse
                                         * @param _demand ABI-encoded demand message
                                         * @param _offer ABI-encoded offer message
                                         * @notice Only current provider can call it
                                         */
                                        function createLiability(
                                            bytes calldata _demand,
                                            bytes calldata _offer
                                        ) external returns (bool);
                                    
                                        /**
                                         * @dev Finalize liability smart contract assigned to this lighthouse
                                         * @param _liability smart contract address
                                         * @param _result report of work
                                         * @param _success work success flag
                                         * @param _signature work signature
                                         */
                                        function finalizeLiability(
                                            address _liability,
                                            bytes calldata _result,
                                            bool _success,
                                            bytes calldata _signature
                                        ) external returns (bool);
                                    }
                                    
                                    // File: contracts/robonomics/interface/IFactory.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    /**
                                     * @title Robonomics liability factory interface
                                     */
                                    contract IFactory {
                                        /**
                                         * @dev New liability created 
                                         */
                                        event NewLiability(address indexed liability);
                                    
                                        /**
                                         * @dev New lighthouse created
                                         */
                                        event NewLighthouse(address indexed lighthouse, string name);
                                    
                                        /**
                                         * @dev Lighthouse address mapping
                                         */
                                        mapping(address => bool) public isLighthouse;
                                    
                                        /**
                                         * @dev Nonce accounting
                                         */
                                        mapping(address => uint256) public nonceOf;
                                    
                                        /**
                                         * @dev Total GAS utilized by Robonomics network
                                         */
                                        uint256 public totalGasConsumed = 0;
                                    
                                        /**
                                         * @dev GAS utilized by liability contracts
                                         */
                                        mapping(address => uint256) public gasConsumedOf;
                                    
                                        /**
                                         * @dev The count of consumed gas for switch to next epoch 
                                         */
                                        uint256 public constant gasEpoch = 347 * 10**10;
                                    
                                        /**
                                         * @dev Current gas price in wei
                                         */
                                        uint256 public gasPrice = 10 * 10**9;
                                    
                                        /**
                                         * @dev XRT emission value for consumed gas
                                         * @param _gas Gas consumed by robonomics program
                                         */
                                        function wnFromGas(uint256 _gas) public view returns (uint256);
                                    
                                        /**
                                         * @dev Create lighthouse smart contract
                                         * @param _minimalStake Minimal stake value of XRT token (one quota price)
                                         * @param _timeoutInBlocks Max time of lighthouse silence in blocks
                                         * @param _name Lighthouse name,
                                         *              example: 'my-name' will create 'my-name.lighthouse.4.robonomics.eth' domain
                                         */
                                        function createLighthouse(
                                            uint256 _minimalStake,
                                            uint256 _timeoutInBlocks,
                                            string calldata _name
                                        ) external returns (ILighthouse);
                                    
                                        /**
                                         * @dev Create robot liability smart contract
                                         * @param _demand ABI-encoded demand message
                                         * @param _offer ABI-encoded offer message
                                         * @notice This method is for lighthouse contract use only
                                         */
                                        function createLiability(
                                            bytes calldata _demand,
                                            bytes calldata _offer
                                        ) external returns (ILiability);
                                    
                                        /**
                                         * @dev Is called after liability creation
                                         * @param _liability Liability contract address
                                         * @param _start_gas Transaction start gas level
                                         * @notice This method is for lighthouse contract use only
                                         */
                                        function liabilityCreated(ILiability _liability, uint256 _start_gas) external returns (bool);
                                    
                                        /**
                                         * @dev Is called after liability finalization
                                         * @param _liability Liability contract address
                                         * @param _start_gas Transaction start gas level
                                         * @notice This method is for lighthouse contract use only
                                         */
                                        function liabilityFinalized(ILiability _liability, uint256 _start_gas) external returns (bool);
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/access/roles/MinterRole.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    contract MinterRole {
                                        using Roles for Roles.Role;
                                    
                                        event MinterAdded(address indexed account);
                                        event MinterRemoved(address indexed account);
                                    
                                        Roles.Role private _minters;
                                    
                                        constructor () internal {
                                            _addMinter(msg.sender);
                                        }
                                    
                                        modifier onlyMinter() {
                                            require(isMinter(msg.sender));
                                            _;
                                        }
                                    
                                        function isMinter(address account) public view returns (bool) {
                                            return _minters.has(account);
                                        }
                                    
                                        function addMinter(address account) public onlyMinter {
                                            _addMinter(account);
                                        }
                                    
                                        function renounceMinter() public {
                                            _removeMinter(msg.sender);
                                        }
                                    
                                        function _addMinter(address account) internal {
                                            _minters.add(account);
                                            emit MinterAdded(account);
                                        }
                                    
                                        function _removeMinter(address account) internal {
                                            _minters.remove(account);
                                            emit MinterRemoved(account);
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    /**
                                     * @title ERC20Mintable
                                     * @dev ERC20 minting logic
                                     */
                                    contract ERC20Mintable is ERC20, MinterRole {
                                        /**
                                         * @dev Function to mint tokens
                                         * @param to The address that will receive the minted tokens.
                                         * @param value The amount of tokens to mint.
                                         * @return A boolean that indicates if the operation was successful.
                                         */
                                        function mint(address to, uint256 value) public onlyMinter returns (bool) {
                                            _mint(to, value);
                                            return true;
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    /**
                                     * @title ERC20Detailed token
                                     * @dev The decimals are only for visualization purposes.
                                     * All the operations are done using the smallest and indivisible token unit,
                                     * just as on Ethereum all the operations are done in wei.
                                     */
                                    contract ERC20Detailed is IERC20 {
                                        string private _name;
                                        string private _symbol;
                                        uint8 private _decimals;
                                    
                                        constructor (string memory name, string memory symbol, uint8 decimals) public {
                                            _name = name;
                                            _symbol = symbol;
                                            _decimals = decimals;
                                        }
                                    
                                        /**
                                         * @return the name of the token.
                                         */
                                        function name() public view returns (string memory) {
                                            return _name;
                                        }
                                    
                                        /**
                                         * @return the symbol of the token.
                                         */
                                        function symbol() public view returns (string memory) {
                                            return _symbol;
                                        }
                                    
                                        /**
                                         * @return the number of decimals of the token.
                                         */
                                        function decimals() public view returns (uint8) {
                                            return _decimals;
                                        }
                                    }
                                    
                                    // File: contracts/robonomics/XRT.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    
                                    contract XRT is ERC20Mintable, ERC20Burnable, ERC20Detailed {
                                        constructor(uint256 _initial_supply) public ERC20Detailed("Robonomics", "XRT", 9) {
                                            _mint(msg.sender, _initial_supply);
                                        }
                                    }
                                    
                                    // File: contracts/robonomics/Lighthouse.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    
                                    
                                    contract Lighthouse is ILighthouse {
                                        using SafeERC20 for XRT;
                                    
                                        IFactory public factory;
                                        XRT      public xrt;
                                    
                                        function setup(XRT _xrt, uint256 _minimalStake, uint256 _timeoutInBlocks) external returns (bool) {
                                            require(factory == IFactory(0) && _minimalStake > 0 && _timeoutInBlocks > 0);
                                    
                                            minimalStake    = _minimalStake;
                                            timeoutInBlocks = _timeoutInBlocks;
                                            factory         = IFactory(msg.sender);
                                            xrt             = _xrt;
                                    
                                            return true;
                                        }
                                    
                                        /**
                                         * @dev Providers index, started from 1
                                         */
                                        mapping(address => uint256) public indexOf;
                                    
                                        function refill(uint256 _value) external returns (bool) {
                                            xrt.safeTransferFrom(msg.sender, address(this), _value);
                                    
                                            if (stakes[msg.sender] == 0) {
                                                require(_value >= minimalStake);
                                                providers.push(msg.sender);
                                                indexOf[msg.sender] = providers.length;
                                                emit Online(msg.sender);
                                            }
                                    
                                            stakes[msg.sender] += _value;
                                            return true;
                                        }
                                    
                                        function withdraw(uint256 _value) external returns (bool) {
                                            require(stakes[msg.sender] >= _value);
                                    
                                            stakes[msg.sender] -= _value;
                                            xrt.safeTransfer(msg.sender, _value);
                                    
                                            // Drop member with zero quota
                                            if (quotaOf(msg.sender) == 0) {
                                                uint256 balance = stakes[msg.sender];
                                                stakes[msg.sender] = 0;
                                                xrt.safeTransfer(msg.sender, balance);
                                                
                                                uint256 senderIndex = indexOf[msg.sender] - 1;
                                                uint256 lastIndex = providers.length - 1;
                                                if (senderIndex < lastIndex)
                                                    providers[senderIndex] = providers[lastIndex];
                                    
                                                providers.length -= 1;
                                                indexOf[msg.sender] = 0;
                                    
                                                emit Offline(msg.sender);
                                            }
                                            return true;
                                        }
                                    
                                        function keepAliveTransaction() internal {
                                            if (timeoutInBlocks < block.number - keepAliveBlock) {
                                                // Set up the marker according to provider index
                                                marker = indexOf[msg.sender];
                                    
                                                // Thransaction sender should be a registered provider
                                                require(marker > 0 && marker <= providers.length);
                                    
                                                // Allocate new quota
                                                quota = quotaOf(providers[marker - 1]);
                                    
                                                // Current provider signal
                                                emit Current(providers[marker - 1], quota);
                                            }
                                    
                                            // Store transaction sending block
                                            keepAliveBlock = block.number;
                                        }
                                    
                                        function quotedTransaction() internal {
                                            // Don't premit transactions without providers on board
                                            require(providers.length > 0);
                                    
                                            // Zero quota guard
                                            // XXX: When quota for some reasons is zero, DoS will be preverted by keepalive transaction
                                            require(quota > 0);
                                    
                                            // Only provider with marker can to send transaction
                                            require(msg.sender == providers[marker - 1]);
                                    
                                            // Consume one quota for transaction sending
                                            if (quota > 1) {
                                                quota -= 1;
                                            } else {
                                                // Step over marker
                                                marker = marker % providers.length + 1;
                                    
                                                // Allocate new quota
                                                quota = quotaOf(providers[marker - 1]);
                                    
                                                // Current provider signal
                                                emit Current(providers[marker - 1], quota);
                                            }
                                        }
                                    
                                        function startGas() internal view returns (uint256 gas) {
                                            // the total amount of gas the tx is DataFee + TxFee + ExecutionGas
                                            // ExecutionGas
                                            gas = gasleft();
                                            // TxFee
                                            gas += 21000;
                                            // DataFee
                                            for (uint256 i = 0; i < msg.data.length; ++i)
                                                gas += msg.data[i] == 0 ? 4 : 68;
                                        }
                                    
                                        function createLiability(
                                            bytes calldata _demand,
                                            bytes calldata _offer
                                        )
                                            external
                                            returns (bool)
                                        {
                                            // Gas with estimation error
                                            uint256 gas = startGas() + 4887;
                                    
                                            keepAliveTransaction();
                                            quotedTransaction();
                                    
                                            ILiability liability = factory.createLiability(_demand, _offer);
                                            require(liability != ILiability(0));
                                            require(factory.liabilityCreated(liability, gas - gasleft()));
                                            return true;
                                        }
                                    
                                        function finalizeLiability(
                                            address _liability,
                                            bytes calldata _result,
                                            bool _success,
                                            bytes calldata _signature
                                        )
                                            external
                                            returns (bool)
                                        {
                                            // Gas with estimation error
                                            uint256 gas = startGas() + 22335;
                                    
                                            keepAliveTransaction();
                                            quotedTransaction();
                                    
                                            ILiability liability = ILiability(_liability);
                                            require(factory.gasConsumedOf(_liability) > 0);
                                            require(liability.finalize(_result, _success, _signature));
                                            require(factory.liabilityFinalized(liability, gas - gasleft()));
                                            return true;
                                        }
                                    }
                                    
                                    // File: contracts/robonomics/interface/IValidator.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @dev Observing network contract interface
                                     */
                                    contract IValidator {
                                        /**
                                         * @dev Be sure than address is really validator
                                         * @return true when validator address in argument
                                         */
                                        function isValidator(address _validator) external returns (bool);
                                    }
                                    
                                    // File: contracts/robonomics/Liability.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    contract Liability is ILiability {
                                        using ECDSA for bytes32;
                                        using SafeERC20 for XRT;
                                        using SafeERC20 for ERC20;
                                    
                                        address public factory;
                                        XRT     public xrt;
                                    
                                        function setup(XRT _xrt) external returns (bool) {
                                            require(factory == address(0));
                                    
                                            factory = msg.sender;
                                            xrt     = _xrt;
                                    
                                            return true;
                                        }
                                    
                                        function demand(
                                            bytes   calldata _model,
                                            bytes   calldata _objective,
                                    
                                            address _token,
                                            uint256 _cost,
                                    
                                            address _lighthouse,
                                    
                                            address _validator,
                                            uint256 _validator_fee,
                                    
                                            uint256 _deadline,
                                            address _sender,
                                            bytes   calldata _signature
                                        )
                                            external
                                            returns (bool)
                                        {
                                            require(msg.sender == factory);
                                            require(block.number < _deadline);
                                    
                                            model        = _model;
                                            objective    = _objective;
                                            token        = _token;
                                            cost         = _cost;
                                            lighthouse   = _lighthouse;
                                            validator    = _validator;
                                            validatorFee = _validator_fee;
                                    
                                            demandHash = keccak256(abi.encodePacked(
                                                _model
                                              , _objective
                                              , _token
                                              , _cost
                                              , _lighthouse
                                              , _validator
                                              , _validator_fee
                                              , _deadline
                                              , IFactory(factory).nonceOf(_sender)
                                              , _sender
                                            ));
                                    
                                            promisee = demandHash
                                                .toEthSignedMessageHash()
                                                .recover(_signature);
                                            require(promisee == _sender);
                                            return true;
                                        }
                                    
                                        function offer(
                                            bytes   calldata _model,
                                            bytes   calldata _objective,
                                            
                                            address _token,
                                            uint256 _cost,
                                    
                                            address _validator,
                                    
                                            address _lighthouse,
                                            uint256 _lighthouse_fee,
                                    
                                            uint256 _deadline,
                                            address _sender,
                                            bytes   calldata _signature
                                        )
                                            external
                                            returns (bool)
                                        {
                                            require(msg.sender == factory);
                                            require(block.number < _deadline);
                                            require(keccak256(model) == keccak256(_model));
                                            require(keccak256(objective) == keccak256(_objective));
                                            require(_token == token);
                                            require(_cost == cost);
                                            require(_lighthouse == lighthouse);
                                            require(_validator == validator);
                                    
                                            lighthouseFee = _lighthouse_fee;
                                    
                                            offerHash = keccak256(abi.encodePacked(
                                                _model
                                              , _objective
                                              , _token
                                              , _cost
                                              , _validator
                                              , _lighthouse
                                              , _lighthouse_fee
                                              , _deadline
                                              , IFactory(factory).nonceOf(_sender)
                                              , _sender
                                            ));
                                    
                                            promisor = offerHash
                                                .toEthSignedMessageHash()
                                                .recover(_signature);
                                            require(promisor == _sender);
                                            return true;
                                        }
                                    
                                        function finalize(
                                            bytes calldata _result,
                                            bool  _success,
                                            bytes calldata _signature
                                        )
                                            external
                                            returns (bool)
                                        {
                                            require(msg.sender == lighthouse);
                                            require(!isFinalized);
                                    
                                            isFinalized = true;
                                            result      = _result;
                                            isSuccess   = _success;
                                    
                                            address resultSender = keccak256(abi.encodePacked(this, _result, _success))
                                                .toEthSignedMessageHash()
                                                .recover(_signature);
                                    
                                            if (validator == address(0)) {
                                                require(resultSender == promisor);
                                            } else {
                                                require(IValidator(validator).isValidator(resultSender));
                                                // Transfer validator fee when is set
                                                if (validatorFee > 0)
                                                    xrt.safeTransfer(validator, validatorFee);
                                    
                                            }
                                    
                                            if (cost > 0)
                                                ERC20(token).safeTransfer(isSuccess ? promisor : promisee, cost);
                                    
                                            emit Finalized(isSuccess, result);
                                            return true;
                                        }
                                    }
                                    
                                    // File: contracts/robonomics/Factory.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    contract Factory is IFactory, SingletonHash {
                                        constructor(
                                            address _liability,
                                            address _lighthouse,
                                            DutchAuction _auction,
                                            AbstractENS _ens,
                                            XRT _xrt
                                        ) public {
                                            liabilityCode = _liability;
                                            lighthouseCode = _lighthouse;
                                            auction = _auction;
                                            ens = _ens;
                                            xrt = _xrt;
                                        }
                                    
                                        address public liabilityCode;
                                        address public lighthouseCode;
                                    
                                        using SafeERC20 for XRT;
                                        using SafeERC20 for ERC20;
                                        using SharedCode for address;
                                    
                                        /**
                                         * @dev Robonomics dutch auction contract
                                         */
                                        DutchAuction public auction;
                                    
                                        /**
                                         * @dev Ethereum name system
                                         */
                                        AbstractENS public ens;
                                    
                                        /**
                                         * @dev Robonomics network protocol token
                                         */
                                        XRT public xrt;
                                    
                                        /**
                                         * @dev SMMA filter with function: SMMA(i) = (SMMA(i-1)*(n-1) + PRICE(i)) / n
                                         * @param _prePrice PRICE[n-1]
                                         * @param _price PRICE[n]
                                         * @return filtered price
                                         */
                                        function smma(uint256 _prePrice, uint256 _price) internal pure returns (uint256) {
                                            return (_prePrice * (smmaPeriod - 1) + _price) / smmaPeriod;
                                        }
                                    
                                        /**
                                         * @dev SMMA filter period
                                         */
                                        uint256 private constant smmaPeriod = 1000;
                                    
                                        /**
                                         * @dev XRT emission value for utilized gas
                                         */
                                        function wnFromGas(uint256 _gas) public view returns (uint256) {
                                            // Just return wn=gas*150 when auction isn't finish
                                            if (auction.finalPrice() == 0)
                                                return _gas * 150;
                                    
                                            // Current gas utilization epoch
                                            uint256 epoch = totalGasConsumed / gasEpoch;
                                    
                                            // XRT emission with addition coefficient by gas utilzation epoch
                                            uint256 wn = _gas * 10**9 * gasPrice * 2**epoch / 3**epoch / auction.finalPrice();
                                    
                                            // Check to not permit emission decrease below wn=gas
                                            return wn < _gas ? _gas : wn;
                                        }
                                    
                                        modifier onlyLighthouse {
                                            require(isLighthouse[msg.sender]);
                                    
                                            _;
                                        }
                                    
                                        modifier gasPriceEstimate {
                                            gasPrice = smma(gasPrice, tx.gasprice);
                                    
                                            _;
                                        }
                                    
                                        function createLighthouse(
                                            uint256 _minimalStake,
                                            uint256 _timeoutInBlocks,
                                            string  calldata _name
                                        )
                                            external
                                            returns (ILighthouse lighthouse)
                                        {
                                            bytes32 LIGHTHOUSE_NODE
                                                // lighthouse.5.robonomics.eth
                                                = 0x8d6c004b56cbe83bbfd9dcbd8f45d1f76398267bbb130a4629d822abc1994b96;
                                            bytes32 hname = keccak256(bytes(_name));
                                    
                                            // Name reservation check
                                            bytes32 subnode = keccak256(abi.encodePacked(LIGHTHOUSE_NODE, hname));
                                            require(ens.resolver(subnode) == address(0));
                                    
                                            // Create lighthouse
                                            lighthouse = ILighthouse(lighthouseCode.proxy());
                                            require(Lighthouse(address(lighthouse)).setup(xrt, _minimalStake, _timeoutInBlocks));
                                    
                                            emit NewLighthouse(address(lighthouse), _name);
                                            isLighthouse[address(lighthouse)] = true;
                                    
                                            // Register subnode
                                            ens.setSubnodeOwner(LIGHTHOUSE_NODE, hname, address(this));
                                    
                                            // Register lighthouse address
                                            AbstractResolver resolver = AbstractResolver(ens.resolver(LIGHTHOUSE_NODE));
                                            ens.setResolver(subnode, address(resolver));
                                            resolver.setAddr(subnode, address(lighthouse));
                                        }
                                    
                                        function createLiability(
                                            bytes calldata _demand,
                                            bytes calldata _offer
                                        )
                                            external
                                            onlyLighthouse
                                            returns (ILiability liability)
                                        {
                                            // Create liability
                                            liability = ILiability(liabilityCode.proxy());
                                            require(Liability(address(liability)).setup(xrt));
                                    
                                            emit NewLiability(address(liability));
                                    
                                            // Parse messages
                                            (bool success, bytes memory returnData)
                                                = address(liability).call(abi.encodePacked(bytes4(0x48a984e4), _demand)); // liability.demand(...)
                                            require(success);
                                            singletonHash(liability.demandHash());
                                            nonceOf[liability.promisee()] += 1;
                                    
                                            (success, returnData)
                                                = address(liability).call(abi.encodePacked(bytes4(0x413781d2), _offer)); // liability.offer(...)
                                            require(success);
                                            singletonHash(liability.offerHash());
                                            nonceOf[liability.promisor()] += 1;
                                    
                                            // Check lighthouse
                                            require(isLighthouse[liability.lighthouse()]);
                                    
                                            // Transfer lighthouse fee to lighthouse worker directly
                                            if (liability.lighthouseFee() > 0)
                                                xrt.safeTransferFrom(liability.promisor(),
                                                                     tx.origin,
                                                                     liability.lighthouseFee());
                                    
                                            // Transfer liability security and hold on contract
                                            ERC20 token = ERC20(liability.token());
                                            if (liability.cost() > 0)
                                                token.safeTransferFrom(liability.promisee(),
                                                                       address(liability),
                                                                       liability.cost());
                                    
                                            // Transfer validator fee and hold on contract
                                            if (liability.validator() != address(0) && liability.validatorFee() > 0)
                                                xrt.safeTransferFrom(liability.promisee(),
                                                                     address(liability),
                                                                     liability.validatorFee());
                                         }
                                    
                                        function liabilityCreated(
                                            ILiability _liability,
                                            uint256 _gas
                                        )
                                            external
                                            onlyLighthouse
                                            gasPriceEstimate
                                            returns (bool)
                                        {
                                            address liability = address(_liability);
                                            totalGasConsumed         += _gas;
                                            gasConsumedOf[liability] += _gas;
                                            return true;
                                        }
                                    
                                        function liabilityFinalized(
                                            ILiability _liability,
                                            uint256 _gas
                                        )
                                            external
                                            onlyLighthouse
                                            gasPriceEstimate
                                            returns (bool)
                                        {
                                            address liability = address(_liability);
                                            totalGasConsumed         += _gas;
                                            gasConsumedOf[liability] += _gas;
                                            require(xrt.mint(tx.origin, wnFromGas(gasConsumedOf[liability])));
                                            return true;
                                        }
                                    }

                                    File 2 of 3: Lighthouse
                                    // File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title ERC20 interface
                                     * @dev see https://github.com/ethereum/EIPs/issues/20
                                     */
                                    interface IERC20 {
                                        function transfer(address to, uint256 value) external returns (bool);
                                    
                                        function approve(address spender, uint256 value) external returns (bool);
                                    
                                        function transferFrom(address from, address to, uint256 value) external returns (bool);
                                    
                                        function totalSupply() external view returns (uint256);
                                    
                                        function balanceOf(address who) external view returns (uint256);
                                    
                                        function allowance(address owner, address spender) external view returns (uint256);
                                    
                                        event Transfer(address indexed from, address indexed to, uint256 value);
                                    
                                        event Approval(address indexed owner, address indexed spender, uint256 value);
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/math/SafeMath.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title SafeMath
                                     * @dev Unsigned math operations with safety checks that revert on error
                                     */
                                    library SafeMath {
                                        /**
                                        * @dev Multiplies two unsigned integers, reverts on overflow.
                                        */
                                        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                                            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                                            // benefit is lost if 'b' is also tested.
                                            // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                                            if (a == 0) {
                                                return 0;
                                            }
                                    
                                            uint256 c = a * b;
                                            require(c / a == b);
                                    
                                            return c;
                                        }
                                    
                                        /**
                                        * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
                                        */
                                        function div(uint256 a, uint256 b) internal pure returns (uint256) {
                                            // Solidity only automatically asserts when dividing by 0
                                            require(b > 0);
                                            uint256 c = a / b;
                                            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
                                    
                                            return c;
                                        }
                                    
                                        /**
                                        * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
                                        */
                                        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                                            require(b <= a);
                                            uint256 c = a - b;
                                    
                                            return c;
                                        }
                                    
                                        /**
                                        * @dev Adds two unsigned integers, reverts on overflow.
                                        */
                                        function add(uint256 a, uint256 b) internal pure returns (uint256) {
                                            uint256 c = a + b;
                                            require(c >= a);
                                    
                                            return c;
                                        }
                                    
                                        /**
                                        * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
                                        * reverts when dividing by zero.
                                        */
                                        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                                            require(b != 0);
                                            return a % b;
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    /**
                                     * @title SafeERC20
                                     * @dev Wrappers around ERC20 operations that throw on failure.
                                     * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
                                     * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
                                     */
                                    library SafeERC20 {
                                        using SafeMath for uint256;
                                    
                                        function safeTransfer(IERC20 token, address to, uint256 value) internal {
                                            require(token.transfer(to, value));
                                        }
                                    
                                        function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
                                            require(token.transferFrom(from, to, value));
                                        }
                                    
                                        function safeApprove(IERC20 token, address spender, uint256 value) internal {
                                            // safeApprove should only be called when setting an initial allowance,
                                            // or when resetting it to zero. To increase and decrease it, use
                                            // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
                                            require((value == 0) || (token.allowance(address(this), spender) == 0));
                                            require(token.approve(spender, value));
                                        }
                                    
                                        function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
                                            uint256 newAllowance = token.allowance(address(this), spender).add(value);
                                            require(token.approve(spender, newAllowance));
                                        }
                                    
                                        function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
                                            uint256 newAllowance = token.allowance(address(this), spender).sub(value);
                                            require(token.approve(spender, newAllowance));
                                        }
                                    }
                                    
                                    // File: contracts/robonomics/interface/ILighthouse.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title Robonomics lighthouse contract interface
                                     */
                                    contract ILighthouse {
                                        /**
                                         * @dev Provider going online
                                         */
                                        event Online(address indexed provider);
                                    
                                        /**
                                         * @dev Provider going offline
                                         */
                                        event Offline(address indexed provider);
                                    
                                        /**
                                         * @dev Active robonomics provider
                                         */
                                        event Current(address indexed provider, uint256 indexed quota);
                                    
                                        /**
                                         * @dev Robonomics providers list
                                         */
                                        address[] public providers;
                                    
                                        /**
                                         * @dev Count of robonomics providers on this lighthouse
                                         */
                                        function providersLength() public view returns (uint256)
                                        { return providers.length; }
                                    
                                        /**
                                         * @dev Provider stake distribution
                                         */
                                        mapping(address => uint256) public stakes;
                                    
                                        /**
                                         * @dev Minimal stake to get one quota
                                         */
                                        uint256 public minimalStake;
                                    
                                        /**
                                         * @dev Silence timeout for provider in blocks
                                         */
                                        uint256 public timeoutInBlocks;
                                    
                                        /**
                                         * @dev Block number of last transaction from current provider
                                         */
                                        uint256 public keepAliveBlock;
                                    
                                        /**
                                         * @dev Round robin provider list marker
                                         */
                                        uint256 public marker;
                                    
                                        /**
                                         * @dev Current provider quota
                                         */
                                        uint256 public quota;
                                    
                                        /**
                                         * @dev Get quota of provider
                                         */
                                        function quotaOf(address _provider) public view returns (uint256)
                                        { return stakes[_provider] / minimalStake; }
                                    
                                        /**
                                         * @dev Increase stake and get more quota,
                                         *      one quota - one transaction in round
                                         * @param _value in wn
                                         * @notice XRT should be approved before call this 
                                         */
                                        function refill(uint256 _value) external returns (bool);
                                    
                                        /**
                                         * @dev Decrease stake and get XRT back
                                         * @param _value in wn
                                         */
                                        function withdraw(uint256 _value) external returns (bool);
                                    
                                        /**
                                         * @dev Create liability smart contract assigned to this lighthouse
                                         * @param _demand ABI-encoded demand message
                                         * @param _offer ABI-encoded offer message
                                         * @notice Only current provider can call it
                                         */
                                        function createLiability(
                                            bytes calldata _demand,
                                            bytes calldata _offer
                                        ) external returns (bool);
                                    
                                        /**
                                         * @dev Finalize liability smart contract assigned to this lighthouse
                                         * @param _liability smart contract address
                                         * @param _result report of work
                                         * @param _success work success flag
                                         * @param _signature work signature
                                         */
                                        function finalizeLiability(
                                            address _liability,
                                            bytes calldata _result,
                                            bool _success,
                                            bytes calldata _signature
                                        ) external returns (bool);
                                    }
                                    
                                    // File: contracts/robonomics/interface/ILiability.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title Standard liability smart contract interface
                                     */
                                    contract ILiability {
                                        /**
                                         * @dev Liability termination signal
                                         */
                                        event Finalized(bool indexed success, bytes result);
                                    
                                        /**
                                         * @dev Behaviour model multihash
                                         */
                                        bytes public model;
                                    
                                        /**
                                         * @dev Objective ROSBAG multihash
                                         * @notice ROSBAGv2 is used: http://wiki.ros.org/Bags/Format/2.0 
                                         */
                                        bytes public objective;
                                    
                                        /**
                                         * @dev Report ROSBAG multihash 
                                         * @notice ROSBAGv2 is used: http://wiki.ros.org/Bags/Format/2.0 
                                         */
                                        bytes public result;
                                    
                                        /**
                                         * @dev Payment token address
                                         */
                                        address public token;
                                    
                                        /**
                                         * @dev Liability cost
                                         */
                                        uint256 public cost;
                                    
                                        /**
                                         * @dev Lighthouse fee in wn
                                         */
                                        uint256 public lighthouseFee;
                                    
                                        /**
                                         * @dev Validator fee in wn
                                         */
                                        uint256 public validatorFee;
                                    
                                        /**
                                         * @dev Robonomics demand message hash
                                         */
                                        bytes32 public demandHash;
                                    
                                        /**
                                         * @dev Robonomics offer message hash
                                         */
                                        bytes32 public offerHash;
                                    
                                        /**
                                         * @dev Liability promisor address
                                         */
                                        address public promisor;
                                    
                                        /**
                                         * @dev Liability promisee address
                                         */
                                        address public promisee;
                                    
                                        /**
                                         * @dev Lighthouse assigned to this liability
                                         */
                                        address public lighthouse;
                                    
                                        /**
                                         * @dev Liability validator address
                                         */
                                        address public validator;
                                    
                                        /**
                                         * @dev Liability success flag
                                         */
                                        bool public isSuccess;
                                    
                                        /**
                                         * @dev Liability finalization status flag
                                         */
                                        bool public isFinalized;
                                    
                                        /**
                                         * @dev Deserialize robonomics demand message
                                         * @notice It can be called by factory only
                                         */
                                        function demand(
                                            bytes   calldata _model,
                                            bytes   calldata _objective,
                                    
                                            address _token,
                                            uint256 _cost,
                                    
                                            address _lighthouse,
                                    
                                            address _validator,
                                            uint256 _validator_fee,
                                    
                                            uint256 _deadline,
                                            address _sender,
                                            bytes   calldata _signature
                                        ) external returns (bool);
                                    
                                        /**
                                         * @dev Deserialize robonomics offer message
                                         * @notice It can be called by factory only
                                         */
                                        function offer(
                                            bytes   calldata _model,
                                            bytes   calldata _objective,
                                            
                                            address _token,
                                            uint256 _cost,
                                    
                                            address _validator,
                                    
                                            address _lighthouse,
                                            uint256 _lighthouse_fee,
                                    
                                            uint256 _deadline,
                                            address _sender,
                                            bytes   calldata _signature
                                        ) external returns (bool);
                                    
                                        /**
                                         * @dev Finalize liability contract
                                         * @param _result Result data hash
                                         * @param _success Set 'true' when liability has success result
                                         * @param _signature Result signature: liability address, result and success flag signed by promisor
                                         * @notice It can be called by assigned lighthouse only
                                         */
                                        function finalize(
                                            bytes calldata _result,
                                            bool  _success,
                                            bytes calldata _signature
                                        ) external returns (bool);
                                    }
                                    
                                    // File: contracts/robonomics/interface/IFactory.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    /**
                                     * @title Robonomics liability factory interface
                                     */
                                    contract IFactory {
                                        /**
                                         * @dev New liability created 
                                         */
                                        event NewLiability(address indexed liability);
                                    
                                        /**
                                         * @dev New lighthouse created
                                         */
                                        event NewLighthouse(address indexed lighthouse, string name);
                                    
                                        /**
                                         * @dev Lighthouse address mapping
                                         */
                                        mapping(address => bool) public isLighthouse;
                                    
                                        /**
                                         * @dev Nonce accounting
                                         */
                                        mapping(address => uint256) public nonceOf;
                                    
                                        /**
                                         * @dev Total GAS utilized by Robonomics network
                                         */
                                        uint256 public totalGasConsumed = 0;
                                    
                                        /**
                                         * @dev GAS utilized by liability contracts
                                         */
                                        mapping(address => uint256) public gasConsumedOf;
                                    
                                        /**
                                         * @dev The count of consumed gas for switch to next epoch 
                                         */
                                        uint256 public constant gasEpoch = 347 * 10**10;
                                    
                                        /**
                                         * @dev Current gas price in wei
                                         */
                                        uint256 public gasPrice = 10 * 10**9;
                                    
                                        /**
                                         * @dev XRT emission value for consumed gas
                                         * @param _gas Gas consumed by robonomics program
                                         */
                                        function wnFromGas(uint256 _gas) public view returns (uint256);
                                    
                                        /**
                                         * @dev Create lighthouse smart contract
                                         * @param _minimalStake Minimal stake value of XRT token (one quota price)
                                         * @param _timeoutInBlocks Max time of lighthouse silence in blocks
                                         * @param _name Lighthouse name,
                                         *              example: 'my-name' will create 'my-name.lighthouse.4.robonomics.eth' domain
                                         */
                                        function createLighthouse(
                                            uint256 _minimalStake,
                                            uint256 _timeoutInBlocks,
                                            string calldata _name
                                        ) external returns (ILighthouse);
                                    
                                        /**
                                         * @dev Create robot liability smart contract
                                         * @param _demand ABI-encoded demand message
                                         * @param _offer ABI-encoded offer message
                                         * @notice This method is for lighthouse contract use only
                                         */
                                        function createLiability(
                                            bytes calldata _demand,
                                            bytes calldata _offer
                                        ) external returns (ILiability);
                                    
                                        /**
                                         * @dev Is called after liability creation
                                         * @param _liability Liability contract address
                                         * @param _start_gas Transaction start gas level
                                         * @notice This method is for lighthouse contract use only
                                         */
                                        function liabilityCreated(ILiability _liability, uint256 _start_gas) external returns (bool);
                                    
                                        /**
                                         * @dev Is called after liability finalization
                                         * @param _liability Liability contract address
                                         * @param _start_gas Transaction start gas level
                                         * @notice This method is for lighthouse contract use only
                                         */
                                        function liabilityFinalized(ILiability _liability, uint256 _start_gas) external returns (bool);
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    /**
                                     * @title Standard ERC20 token
                                     *
                                     * @dev Implementation of the basic standard token.
                                     * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
                                     * Originally based on code by FirstBlood:
                                     * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
                                     *
                                     * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for
                                     * all accounts just by listening to said events. Note that this isn't required by the specification, and other
                                     * compliant implementations may not do it.
                                     */
                                    contract ERC20 is IERC20 {
                                        using SafeMath for uint256;
                                    
                                        mapping (address => uint256) private _balances;
                                    
                                        mapping (address => mapping (address => uint256)) private _allowed;
                                    
                                        uint256 private _totalSupply;
                                    
                                        /**
                                        * @dev Total number of tokens in existence
                                        */
                                        function totalSupply() public view returns (uint256) {
                                            return _totalSupply;
                                        }
                                    
                                        /**
                                        * @dev Gets the balance of the specified address.
                                        * @param owner The address to query the balance of.
                                        * @return An uint256 representing the amount owned by the passed address.
                                        */
                                        function balanceOf(address owner) public view returns (uint256) {
                                            return _balances[owner];
                                        }
                                    
                                        /**
                                         * @dev Function to check the amount of tokens that an owner allowed to a spender.
                                         * @param owner address The address which owns the funds.
                                         * @param spender address The address which will spend the funds.
                                         * @return A uint256 specifying the amount of tokens still available for the spender.
                                         */
                                        function allowance(address owner, address spender) public view returns (uint256) {
                                            return _allowed[owner][spender];
                                        }
                                    
                                        /**
                                        * @dev Transfer token for a specified address
                                        * @param to The address to transfer to.
                                        * @param value The amount to be transferred.
                                        */
                                        function transfer(address to, uint256 value) public returns (bool) {
                                            _transfer(msg.sender, to, value);
                                            return true;
                                        }
                                    
                                        /**
                                         * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
                                         * Beware that changing an allowance with this method brings the risk that someone may use both the old
                                         * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
                                         * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
                                         * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
                                         * @param spender The address which will spend the funds.
                                         * @param value The amount of tokens to be spent.
                                         */
                                        function approve(address spender, uint256 value) public returns (bool) {
                                            require(spender != address(0));
                                    
                                            _allowed[msg.sender][spender] = value;
                                            emit Approval(msg.sender, spender, value);
                                            return true;
                                        }
                                    
                                        /**
                                         * @dev Transfer tokens from one address to another.
                                         * Note that while this function emits an Approval event, this is not required as per the specification,
                                         * and other compliant implementations may not emit the event.
                                         * @param from address The address which you want to send tokens from
                                         * @param to address The address which you want to transfer to
                                         * @param value uint256 the amount of tokens to be transferred
                                         */
                                        function transferFrom(address from, address to, uint256 value) public returns (bool) {
                                            _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
                                            _transfer(from, to, value);
                                            emit Approval(from, msg.sender, _allowed[from][msg.sender]);
                                            return true;
                                        }
                                    
                                        /**
                                         * @dev Increase the amount of tokens that an owner allowed to a spender.
                                         * approve should be called when allowed_[_spender] == 0. To increment
                                         * allowed value is better to use this function to avoid 2 calls (and wait until
                                         * the first transaction is mined)
                                         * From MonolithDAO Token.sol
                                         * Emits an Approval event.
                                         * @param spender The address which will spend the funds.
                                         * @param addedValue The amount of tokens to increase the allowance by.
                                         */
                                        function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
                                            require(spender != address(0));
                                    
                                            _allowed[msg.sender][spender] = _allowed[msg.sender][spender].add(addedValue);
                                            emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
                                            return true;
                                        }
                                    
                                        /**
                                         * @dev Decrease the amount of tokens that an owner allowed to a spender.
                                         * approve should be called when allowed_[_spender] == 0. To decrement
                                         * allowed value is better to use this function to avoid 2 calls (and wait until
                                         * the first transaction is mined)
                                         * From MonolithDAO Token.sol
                                         * Emits an Approval event.
                                         * @param spender The address which will spend the funds.
                                         * @param subtractedValue The amount of tokens to decrease the allowance by.
                                         */
                                        function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
                                            require(spender != address(0));
                                    
                                            _allowed[msg.sender][spender] = _allowed[msg.sender][spender].sub(subtractedValue);
                                            emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
                                            return true;
                                        }
                                    
                                        /**
                                        * @dev Transfer token for a specified addresses
                                        * @param from The address to transfer from.
                                        * @param to The address to transfer to.
                                        * @param value The amount to be transferred.
                                        */
                                        function _transfer(address from, address to, uint256 value) internal {
                                            require(to != address(0));
                                    
                                            _balances[from] = _balances[from].sub(value);
                                            _balances[to] = _balances[to].add(value);
                                            emit Transfer(from, to, value);
                                        }
                                    
                                        /**
                                         * @dev Internal function that mints an amount of the token and assigns it to
                                         * an account. This encapsulates the modification of balances such that the
                                         * proper events are emitted.
                                         * @param account The account that will receive the created tokens.
                                         * @param value The amount that will be created.
                                         */
                                        function _mint(address account, uint256 value) internal {
                                            require(account != address(0));
                                    
                                            _totalSupply = _totalSupply.add(value);
                                            _balances[account] = _balances[account].add(value);
                                            emit Transfer(address(0), account, value);
                                        }
                                    
                                        /**
                                         * @dev Internal function that burns an amount of the token of a given
                                         * account.
                                         * @param account The account whose tokens will be burnt.
                                         * @param value The amount that will be burnt.
                                         */
                                        function _burn(address account, uint256 value) internal {
                                            require(account != address(0));
                                    
                                            _totalSupply = _totalSupply.sub(value);
                                            _balances[account] = _balances[account].sub(value);
                                            emit Transfer(account, address(0), value);
                                        }
                                    
                                        /**
                                         * @dev Internal function that burns an amount of the token of a given
                                         * account, deducting from the sender's allowance for said account. Uses the
                                         * internal burn function.
                                         * Emits an Approval event (reflecting the reduced allowance).
                                         * @param account The account whose tokens will be burnt.
                                         * @param value The amount that will be burnt.
                                         */
                                        function _burnFrom(address account, uint256 value) internal {
                                            _allowed[account][msg.sender] = _allowed[account][msg.sender].sub(value);
                                            _burn(account, value);
                                            emit Approval(account, msg.sender, _allowed[account][msg.sender]);
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/access/Roles.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title Roles
                                     * @dev Library for managing addresses assigned to a Role.
                                     */
                                    library Roles {
                                        struct Role {
                                            mapping (address => bool) bearer;
                                        }
                                    
                                        /**
                                         * @dev give an account access to this role
                                         */
                                        function add(Role storage role, address account) internal {
                                            require(account != address(0));
                                            require(!has(role, account));
                                    
                                            role.bearer[account] = true;
                                        }
                                    
                                        /**
                                         * @dev remove an account's access to this role
                                         */
                                        function remove(Role storage role, address account) internal {
                                            require(account != address(0));
                                            require(has(role, account));
                                    
                                            role.bearer[account] = false;
                                        }
                                    
                                        /**
                                         * @dev check if an account has this role
                                         * @return bool
                                         */
                                        function has(Role storage role, address account) internal view returns (bool) {
                                            require(account != address(0));
                                            return role.bearer[account];
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/access/roles/MinterRole.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    contract MinterRole {
                                        using Roles for Roles.Role;
                                    
                                        event MinterAdded(address indexed account);
                                        event MinterRemoved(address indexed account);
                                    
                                        Roles.Role private _minters;
                                    
                                        constructor () internal {
                                            _addMinter(msg.sender);
                                        }
                                    
                                        modifier onlyMinter() {
                                            require(isMinter(msg.sender));
                                            _;
                                        }
                                    
                                        function isMinter(address account) public view returns (bool) {
                                            return _minters.has(account);
                                        }
                                    
                                        function addMinter(address account) public onlyMinter {
                                            _addMinter(account);
                                        }
                                    
                                        function renounceMinter() public {
                                            _removeMinter(msg.sender);
                                        }
                                    
                                        function _addMinter(address account) internal {
                                            _minters.add(account);
                                            emit MinterAdded(account);
                                        }
                                    
                                        function _removeMinter(address account) internal {
                                            _minters.remove(account);
                                            emit MinterRemoved(account);
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    /**
                                     * @title ERC20Mintable
                                     * @dev ERC20 minting logic
                                     */
                                    contract ERC20Mintable is ERC20, MinterRole {
                                        /**
                                         * @dev Function to mint tokens
                                         * @param to The address that will receive the minted tokens.
                                         * @param value The amount of tokens to mint.
                                         * @return A boolean that indicates if the operation was successful.
                                         */
                                        function mint(address to, uint256 value) public onlyMinter returns (bool) {
                                            _mint(to, value);
                                            return true;
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    /**
                                     * @title Burnable Token
                                     * @dev Token that can be irreversibly burned (destroyed).
                                     */
                                    contract ERC20Burnable is ERC20 {
                                        /**
                                         * @dev Burns a specific amount of tokens.
                                         * @param value The amount of token to be burned.
                                         */
                                        function burn(uint256 value) public {
                                            _burn(msg.sender, value);
                                        }
                                    
                                        /**
                                         * @dev Burns a specific amount of tokens from the target address and decrements allowance
                                         * @param from address The address which you want to send tokens from
                                         * @param value uint256 The amount of token to be burned
                                         */
                                        function burnFrom(address from, uint256 value) public {
                                            _burnFrom(from, value);
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    /**
                                     * @title ERC20Detailed token
                                     * @dev The decimals are only for visualization purposes.
                                     * All the operations are done using the smallest and indivisible token unit,
                                     * just as on Ethereum all the operations are done in wei.
                                     */
                                    contract ERC20Detailed is IERC20 {
                                        string private _name;
                                        string private _symbol;
                                        uint8 private _decimals;
                                    
                                        constructor (string memory name, string memory symbol, uint8 decimals) public {
                                            _name = name;
                                            _symbol = symbol;
                                            _decimals = decimals;
                                        }
                                    
                                        /**
                                         * @return the name of the token.
                                         */
                                        function name() public view returns (string memory) {
                                            return _name;
                                        }
                                    
                                        /**
                                         * @return the symbol of the token.
                                         */
                                        function symbol() public view returns (string memory) {
                                            return _symbol;
                                        }
                                    
                                        /**
                                         * @return the number of decimals of the token.
                                         */
                                        function decimals() public view returns (uint8) {
                                            return _decimals;
                                        }
                                    }
                                    
                                    // File: contracts/robonomics/XRT.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    
                                    contract XRT is ERC20Mintable, ERC20Burnable, ERC20Detailed {
                                        constructor(uint256 _initial_supply) public ERC20Detailed("Robonomics", "XRT", 9) {
                                            _mint(msg.sender, _initial_supply);
                                        }
                                    }
                                    
                                    // File: contracts/robonomics/Lighthouse.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    
                                    
                                    contract Lighthouse is ILighthouse {
                                        using SafeERC20 for XRT;
                                    
                                        IFactory public factory;
                                        XRT      public xrt;
                                    
                                        function setup(XRT _xrt, uint256 _minimalStake, uint256 _timeoutInBlocks) external returns (bool) {
                                            require(factory == IFactory(0) && _minimalStake > 0 && _timeoutInBlocks > 0);
                                    
                                            minimalStake    = _minimalStake;
                                            timeoutInBlocks = _timeoutInBlocks;
                                            factory         = IFactory(msg.sender);
                                            xrt             = _xrt;
                                    
                                            return true;
                                        }
                                    
                                        /**
                                         * @dev Providers index, started from 1
                                         */
                                        mapping(address => uint256) public indexOf;
                                    
                                        function refill(uint256 _value) external returns (bool) {
                                            xrt.safeTransferFrom(msg.sender, address(this), _value);
                                    
                                            if (stakes[msg.sender] == 0) {
                                                require(_value >= minimalStake);
                                                providers.push(msg.sender);
                                                indexOf[msg.sender] = providers.length;
                                                emit Online(msg.sender);
                                            }
                                    
                                            stakes[msg.sender] += _value;
                                            return true;
                                        }
                                    
                                        function withdraw(uint256 _value) external returns (bool) {
                                            require(stakes[msg.sender] >= _value);
                                    
                                            stakes[msg.sender] -= _value;
                                            xrt.safeTransfer(msg.sender, _value);
                                    
                                            // Drop member with zero quota
                                            if (quotaOf(msg.sender) == 0) {
                                                uint256 balance = stakes[msg.sender];
                                                stakes[msg.sender] = 0;
                                                xrt.safeTransfer(msg.sender, balance);
                                                
                                                uint256 senderIndex = indexOf[msg.sender] - 1;
                                                uint256 lastIndex = providers.length - 1;
                                                if (senderIndex < lastIndex)
                                                    providers[senderIndex] = providers[lastIndex];
                                    
                                                providers.length -= 1;
                                                indexOf[msg.sender] = 0;
                                    
                                                emit Offline(msg.sender);
                                            }
                                            return true;
                                        }
                                    
                                        function keepAliveTransaction() internal {
                                            if (timeoutInBlocks < block.number - keepAliveBlock) {
                                                // Set up the marker according to provider index
                                                marker = indexOf[msg.sender];
                                    
                                                // Thransaction sender should be a registered provider
                                                require(marker > 0 && marker <= providers.length);
                                    
                                                // Allocate new quota
                                                quota = quotaOf(providers[marker - 1]);
                                    
                                                // Current provider signal
                                                emit Current(providers[marker - 1], quota);
                                            }
                                    
                                            // Store transaction sending block
                                            keepAliveBlock = block.number;
                                        }
                                    
                                        function quotedTransaction() internal {
                                            // Don't premit transactions without providers on board
                                            require(providers.length > 0);
                                    
                                            // Zero quota guard
                                            // XXX: When quota for some reasons is zero, DoS will be preverted by keepalive transaction
                                            require(quota > 0);
                                    
                                            // Only provider with marker can to send transaction
                                            require(msg.sender == providers[marker - 1]);
                                    
                                            // Consume one quota for transaction sending
                                            if (quota > 1) {
                                                quota -= 1;
                                            } else {
                                                // Step over marker
                                                marker = marker % providers.length + 1;
                                    
                                                // Allocate new quota
                                                quota = quotaOf(providers[marker - 1]);
                                    
                                                // Current provider signal
                                                emit Current(providers[marker - 1], quota);
                                            }
                                        }
                                    
                                        function startGas() internal view returns (uint256 gas) {
                                            // the total amount of gas the tx is DataFee + TxFee + ExecutionGas
                                            // ExecutionGas
                                            gas = gasleft();
                                            // TxFee
                                            gas += 21000;
                                            // DataFee
                                            for (uint256 i = 0; i < msg.data.length; ++i)
                                                gas += msg.data[i] == 0 ? 4 : 68;
                                        }
                                    
                                        function createLiability(
                                            bytes calldata _demand,
                                            bytes calldata _offer
                                        )
                                            external
                                            returns (bool)
                                        {
                                            // Gas with estimation error
                                            uint256 gas = startGas() + 4887;
                                    
                                            keepAliveTransaction();
                                            quotedTransaction();
                                    
                                            ILiability liability = factory.createLiability(_demand, _offer);
                                            require(liability != ILiability(0));
                                            require(factory.liabilityCreated(liability, gas - gasleft()));
                                            return true;
                                        }
                                    
                                        function finalizeLiability(
                                            address _liability,
                                            bytes calldata _result,
                                            bool _success,
                                            bytes calldata _signature
                                        )
                                            external
                                            returns (bool)
                                        {
                                            // Gas with estimation error
                                            uint256 gas = startGas() + 22335;
                                    
                                            keepAliveTransaction();
                                            quotedTransaction();
                                    
                                            ILiability liability = ILiability(_liability);
                                            require(factory.gasConsumedOf(_liability) > 0);
                                            require(liability.finalize(_result, _success, _signature));
                                            require(factory.liabilityFinalized(liability, gas - gasleft()));
                                            return true;
                                        }
                                    }

                                    File 3 of 3: Liability
                                    // File: openzeppelin-solidity/contracts/cryptography/ECDSA.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title Elliptic curve signature operations
                                     * @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
                                     * TODO Remove this library once solidity supports passing a signature to ecrecover.
                                     * See https://github.com/ethereum/solidity/issues/864
                                     */
                                    
                                    library ECDSA {
                                        /**
                                         * @dev Recover signer address from a message by using their signature
                                         * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
                                         * @param signature bytes signature, the signature is generated using web3.eth.sign()
                                         */
                                        function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
                                            bytes32 r;
                                            bytes32 s;
                                            uint8 v;
                                    
                                            // Check the signature length
                                            if (signature.length != 65) {
                                                return (address(0));
                                            }
                                    
                                            // Divide the signature in r, s and v variables
                                            // ecrecover takes the signature parameters, and the only way to get them
                                            // currently is to use assembly.
                                            // solhint-disable-next-line no-inline-assembly
                                            assembly {
                                                r := mload(add(signature, 0x20))
                                                s := mload(add(signature, 0x40))
                                                v := byte(0, mload(add(signature, 0x60)))
                                            }
                                    
                                            // Version of signature should be 27 or 28, but 0 and 1 are also possible versions
                                            if (v < 27) {
                                                v += 27;
                                            }
                                    
                                            // If the version is correct return the signer address
                                            if (v != 27 && v != 28) {
                                                return (address(0));
                                            } else {
                                                return ecrecover(hash, v, r, s);
                                            }
                                        }
                                    
                                        /**
                                         * toEthSignedMessageHash
                                         * @dev prefix a bytes32 value with "\x19Ethereum Signed Message:"
                                         * and hash the result
                                         */
                                        function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
                                            // 32 is the length in bytes of hash,
                                            // enforced by the type signature above
                                            return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title ERC20 interface
                                     * @dev see https://github.com/ethereum/EIPs/issues/20
                                     */
                                    interface IERC20 {
                                        function transfer(address to, uint256 value) external returns (bool);
                                    
                                        function approve(address spender, uint256 value) external returns (bool);
                                    
                                        function transferFrom(address from, address to, uint256 value) external returns (bool);
                                    
                                        function totalSupply() external view returns (uint256);
                                    
                                        function balanceOf(address who) external view returns (uint256);
                                    
                                        function allowance(address owner, address spender) external view returns (uint256);
                                    
                                        event Transfer(address indexed from, address indexed to, uint256 value);
                                    
                                        event Approval(address indexed owner, address indexed spender, uint256 value);
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/math/SafeMath.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title SafeMath
                                     * @dev Unsigned math operations with safety checks that revert on error
                                     */
                                    library SafeMath {
                                        /**
                                        * @dev Multiplies two unsigned integers, reverts on overflow.
                                        */
                                        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                                            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                                            // benefit is lost if 'b' is also tested.
                                            // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                                            if (a == 0) {
                                                return 0;
                                            }
                                    
                                            uint256 c = a * b;
                                            require(c / a == b);
                                    
                                            return c;
                                        }
                                    
                                        /**
                                        * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
                                        */
                                        function div(uint256 a, uint256 b) internal pure returns (uint256) {
                                            // Solidity only automatically asserts when dividing by 0
                                            require(b > 0);
                                            uint256 c = a / b;
                                            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
                                    
                                            return c;
                                        }
                                    
                                        /**
                                        * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
                                        */
                                        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                                            require(b <= a);
                                            uint256 c = a - b;
                                    
                                            return c;
                                        }
                                    
                                        /**
                                        * @dev Adds two unsigned integers, reverts on overflow.
                                        */
                                        function add(uint256 a, uint256 b) internal pure returns (uint256) {
                                            uint256 c = a + b;
                                            require(c >= a);
                                    
                                            return c;
                                        }
                                    
                                        /**
                                        * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
                                        * reverts when dividing by zero.
                                        */
                                        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                                            require(b != 0);
                                            return a % b;
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    /**
                                     * @title SafeERC20
                                     * @dev Wrappers around ERC20 operations that throw on failure.
                                     * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
                                     * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
                                     */
                                    library SafeERC20 {
                                        using SafeMath for uint256;
                                    
                                        function safeTransfer(IERC20 token, address to, uint256 value) internal {
                                            require(token.transfer(to, value));
                                        }
                                    
                                        function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
                                            require(token.transferFrom(from, to, value));
                                        }
                                    
                                        function safeApprove(IERC20 token, address spender, uint256 value) internal {
                                            // safeApprove should only be called when setting an initial allowance,
                                            // or when resetting it to zero. To increase and decrease it, use
                                            // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
                                            require((value == 0) || (token.allowance(address(this), spender) == 0));
                                            require(token.approve(spender, value));
                                        }
                                    
                                        function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
                                            uint256 newAllowance = token.allowance(address(this), spender).add(value);
                                            require(token.approve(spender, newAllowance));
                                        }
                                    
                                        function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
                                            uint256 newAllowance = token.allowance(address(this), spender).sub(value);
                                            require(token.approve(spender, newAllowance));
                                        }
                                    }
                                    
                                    // File: contracts/robonomics/interface/ILiability.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title Standard liability smart contract interface
                                     */
                                    contract ILiability {
                                        /**
                                         * @dev Liability termination signal
                                         */
                                        event Finalized(bool indexed success, bytes result);
                                    
                                        /**
                                         * @dev Behaviour model multihash
                                         */
                                        bytes public model;
                                    
                                        /**
                                         * @dev Objective ROSBAG multihash
                                         * @notice ROSBAGv2 is used: http://wiki.ros.org/Bags/Format/2.0 
                                         */
                                        bytes public objective;
                                    
                                        /**
                                         * @dev Report ROSBAG multihash 
                                         * @notice ROSBAGv2 is used: http://wiki.ros.org/Bags/Format/2.0 
                                         */
                                        bytes public result;
                                    
                                        /**
                                         * @dev Payment token address
                                         */
                                        address public token;
                                    
                                        /**
                                         * @dev Liability cost
                                         */
                                        uint256 public cost;
                                    
                                        /**
                                         * @dev Lighthouse fee in wn
                                         */
                                        uint256 public lighthouseFee;
                                    
                                        /**
                                         * @dev Validator fee in wn
                                         */
                                        uint256 public validatorFee;
                                    
                                        /**
                                         * @dev Robonomics demand message hash
                                         */
                                        bytes32 public demandHash;
                                    
                                        /**
                                         * @dev Robonomics offer message hash
                                         */
                                        bytes32 public offerHash;
                                    
                                        /**
                                         * @dev Liability promisor address
                                         */
                                        address public promisor;
                                    
                                        /**
                                         * @dev Liability promisee address
                                         */
                                        address public promisee;
                                    
                                        /**
                                         * @dev Lighthouse assigned to this liability
                                         */
                                        address public lighthouse;
                                    
                                        /**
                                         * @dev Liability validator address
                                         */
                                        address public validator;
                                    
                                        /**
                                         * @dev Liability success flag
                                         */
                                        bool public isSuccess;
                                    
                                        /**
                                         * @dev Liability finalization status flag
                                         */
                                        bool public isFinalized;
                                    
                                        /**
                                         * @dev Deserialize robonomics demand message
                                         * @notice It can be called by factory only
                                         */
                                        function demand(
                                            bytes   calldata _model,
                                            bytes   calldata _objective,
                                    
                                            address _token,
                                            uint256 _cost,
                                    
                                            address _lighthouse,
                                    
                                            address _validator,
                                            uint256 _validator_fee,
                                    
                                            uint256 _deadline,
                                            address _sender,
                                            bytes   calldata _signature
                                        ) external returns (bool);
                                    
                                        /**
                                         * @dev Deserialize robonomics offer message
                                         * @notice It can be called by factory only
                                         */
                                        function offer(
                                            bytes   calldata _model,
                                            bytes   calldata _objective,
                                            
                                            address _token,
                                            uint256 _cost,
                                    
                                            address _validator,
                                    
                                            address _lighthouse,
                                            uint256 _lighthouse_fee,
                                    
                                            uint256 _deadline,
                                            address _sender,
                                            bytes   calldata _signature
                                        ) external returns (bool);
                                    
                                        /**
                                         * @dev Finalize liability contract
                                         * @param _result Result data hash
                                         * @param _success Set 'true' when liability has success result
                                         * @param _signature Result signature: liability address, result and success flag signed by promisor
                                         * @notice It can be called by assigned lighthouse only
                                         */
                                        function finalize(
                                            bytes calldata _result,
                                            bool  _success,
                                            bytes calldata _signature
                                        ) external returns (bool);
                                    }
                                    
                                    // File: contracts/robonomics/interface/IValidator.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @dev Observing network contract interface
                                     */
                                    contract IValidator {
                                        /**
                                         * @dev Be sure than address is really validator
                                         * @return true when validator address in argument
                                         */
                                        function isValidator(address _validator) external returns (bool);
                                    }
                                    
                                    // File: contracts/robonomics/interface/ILighthouse.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title Robonomics lighthouse contract interface
                                     */
                                    contract ILighthouse {
                                        /**
                                         * @dev Provider going online
                                         */
                                        event Online(address indexed provider);
                                    
                                        /**
                                         * @dev Provider going offline
                                         */
                                        event Offline(address indexed provider);
                                    
                                        /**
                                         * @dev Active robonomics provider
                                         */
                                        event Current(address indexed provider, uint256 indexed quota);
                                    
                                        /**
                                         * @dev Robonomics providers list
                                         */
                                        address[] public providers;
                                    
                                        /**
                                         * @dev Count of robonomics providers on this lighthouse
                                         */
                                        function providersLength() public view returns (uint256)
                                        { return providers.length; }
                                    
                                        /**
                                         * @dev Provider stake distribution
                                         */
                                        mapping(address => uint256) public stakes;
                                    
                                        /**
                                         * @dev Minimal stake to get one quota
                                         */
                                        uint256 public minimalStake;
                                    
                                        /**
                                         * @dev Silence timeout for provider in blocks
                                         */
                                        uint256 public timeoutInBlocks;
                                    
                                        /**
                                         * @dev Block number of last transaction from current provider
                                         */
                                        uint256 public keepAliveBlock;
                                    
                                        /**
                                         * @dev Round robin provider list marker
                                         */
                                        uint256 public marker;
                                    
                                        /**
                                         * @dev Current provider quota
                                         */
                                        uint256 public quota;
                                    
                                        /**
                                         * @dev Get quota of provider
                                         */
                                        function quotaOf(address _provider) public view returns (uint256)
                                        { return stakes[_provider] / minimalStake; }
                                    
                                        /**
                                         * @dev Increase stake and get more quota,
                                         *      one quota - one transaction in round
                                         * @param _value in wn
                                         * @notice XRT should be approved before call this 
                                         */
                                        function refill(uint256 _value) external returns (bool);
                                    
                                        /**
                                         * @dev Decrease stake and get XRT back
                                         * @param _value in wn
                                         */
                                        function withdraw(uint256 _value) external returns (bool);
                                    
                                        /**
                                         * @dev Create liability smart contract assigned to this lighthouse
                                         * @param _demand ABI-encoded demand message
                                         * @param _offer ABI-encoded offer message
                                         * @notice Only current provider can call it
                                         */
                                        function createLiability(
                                            bytes calldata _demand,
                                            bytes calldata _offer
                                        ) external returns (bool);
                                    
                                        /**
                                         * @dev Finalize liability smart contract assigned to this lighthouse
                                         * @param _liability smart contract address
                                         * @param _result report of work
                                         * @param _success work success flag
                                         * @param _signature work signature
                                         */
                                        function finalizeLiability(
                                            address _liability,
                                            bytes calldata _result,
                                            bool _success,
                                            bytes calldata _signature
                                        ) external returns (bool);
                                    }
                                    
                                    // File: contracts/robonomics/interface/IFactory.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    /**
                                     * @title Robonomics liability factory interface
                                     */
                                    contract IFactory {
                                        /**
                                         * @dev New liability created 
                                         */
                                        event NewLiability(address indexed liability);
                                    
                                        /**
                                         * @dev New lighthouse created
                                         */
                                        event NewLighthouse(address indexed lighthouse, string name);
                                    
                                        /**
                                         * @dev Lighthouse address mapping
                                         */
                                        mapping(address => bool) public isLighthouse;
                                    
                                        /**
                                         * @dev Nonce accounting
                                         */
                                        mapping(address => uint256) public nonceOf;
                                    
                                        /**
                                         * @dev Total GAS utilized by Robonomics network
                                         */
                                        uint256 public totalGasConsumed = 0;
                                    
                                        /**
                                         * @dev GAS utilized by liability contracts
                                         */
                                        mapping(address => uint256) public gasConsumedOf;
                                    
                                        /**
                                         * @dev The count of consumed gas for switch to next epoch 
                                         */
                                        uint256 public constant gasEpoch = 347 * 10**10;
                                    
                                        /**
                                         * @dev Current gas price in wei
                                         */
                                        uint256 public gasPrice = 10 * 10**9;
                                    
                                        /**
                                         * @dev XRT emission value for consumed gas
                                         * @param _gas Gas consumed by robonomics program
                                         */
                                        function wnFromGas(uint256 _gas) public view returns (uint256);
                                    
                                        /**
                                         * @dev Create lighthouse smart contract
                                         * @param _minimalStake Minimal stake value of XRT token (one quota price)
                                         * @param _timeoutInBlocks Max time of lighthouse silence in blocks
                                         * @param _name Lighthouse name,
                                         *              example: 'my-name' will create 'my-name.lighthouse.4.robonomics.eth' domain
                                         */
                                        function createLighthouse(
                                            uint256 _minimalStake,
                                            uint256 _timeoutInBlocks,
                                            string calldata _name
                                        ) external returns (ILighthouse);
                                    
                                        /**
                                         * @dev Create robot liability smart contract
                                         * @param _demand ABI-encoded demand message
                                         * @param _offer ABI-encoded offer message
                                         * @notice This method is for lighthouse contract use only
                                         */
                                        function createLiability(
                                            bytes calldata _demand,
                                            bytes calldata _offer
                                        ) external returns (ILiability);
                                    
                                        /**
                                         * @dev Is called after liability creation
                                         * @param _liability Liability contract address
                                         * @param _start_gas Transaction start gas level
                                         * @notice This method is for lighthouse contract use only
                                         */
                                        function liabilityCreated(ILiability _liability, uint256 _start_gas) external returns (bool);
                                    
                                        /**
                                         * @dev Is called after liability finalization
                                         * @param _liability Liability contract address
                                         * @param _start_gas Transaction start gas level
                                         * @notice This method is for lighthouse contract use only
                                         */
                                        function liabilityFinalized(ILiability _liability, uint256 _start_gas) external returns (bool);
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    /**
                                     * @title Standard ERC20 token
                                     *
                                     * @dev Implementation of the basic standard token.
                                     * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
                                     * Originally based on code by FirstBlood:
                                     * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
                                     *
                                     * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for
                                     * all accounts just by listening to said events. Note that this isn't required by the specification, and other
                                     * compliant implementations may not do it.
                                     */
                                    contract ERC20 is IERC20 {
                                        using SafeMath for uint256;
                                    
                                        mapping (address => uint256) private _balances;
                                    
                                        mapping (address => mapping (address => uint256)) private _allowed;
                                    
                                        uint256 private _totalSupply;
                                    
                                        /**
                                        * @dev Total number of tokens in existence
                                        */
                                        function totalSupply() public view returns (uint256) {
                                            return _totalSupply;
                                        }
                                    
                                        /**
                                        * @dev Gets the balance of the specified address.
                                        * @param owner The address to query the balance of.
                                        * @return An uint256 representing the amount owned by the passed address.
                                        */
                                        function balanceOf(address owner) public view returns (uint256) {
                                            return _balances[owner];
                                        }
                                    
                                        /**
                                         * @dev Function to check the amount of tokens that an owner allowed to a spender.
                                         * @param owner address The address which owns the funds.
                                         * @param spender address The address which will spend the funds.
                                         * @return A uint256 specifying the amount of tokens still available for the spender.
                                         */
                                        function allowance(address owner, address spender) public view returns (uint256) {
                                            return _allowed[owner][spender];
                                        }
                                    
                                        /**
                                        * @dev Transfer token for a specified address
                                        * @param to The address to transfer to.
                                        * @param value The amount to be transferred.
                                        */
                                        function transfer(address to, uint256 value) public returns (bool) {
                                            _transfer(msg.sender, to, value);
                                            return true;
                                        }
                                    
                                        /**
                                         * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
                                         * Beware that changing an allowance with this method brings the risk that someone may use both the old
                                         * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
                                         * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
                                         * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
                                         * @param spender The address which will spend the funds.
                                         * @param value The amount of tokens to be spent.
                                         */
                                        function approve(address spender, uint256 value) public returns (bool) {
                                            require(spender != address(0));
                                    
                                            _allowed[msg.sender][spender] = value;
                                            emit Approval(msg.sender, spender, value);
                                            return true;
                                        }
                                    
                                        /**
                                         * @dev Transfer tokens from one address to another.
                                         * Note that while this function emits an Approval event, this is not required as per the specification,
                                         * and other compliant implementations may not emit the event.
                                         * @param from address The address which you want to send tokens from
                                         * @param to address The address which you want to transfer to
                                         * @param value uint256 the amount of tokens to be transferred
                                         */
                                        function transferFrom(address from, address to, uint256 value) public returns (bool) {
                                            _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
                                            _transfer(from, to, value);
                                            emit Approval(from, msg.sender, _allowed[from][msg.sender]);
                                            return true;
                                        }
                                    
                                        /**
                                         * @dev Increase the amount of tokens that an owner allowed to a spender.
                                         * approve should be called when allowed_[_spender] == 0. To increment
                                         * allowed value is better to use this function to avoid 2 calls (and wait until
                                         * the first transaction is mined)
                                         * From MonolithDAO Token.sol
                                         * Emits an Approval event.
                                         * @param spender The address which will spend the funds.
                                         * @param addedValue The amount of tokens to increase the allowance by.
                                         */
                                        function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
                                            require(spender != address(0));
                                    
                                            _allowed[msg.sender][spender] = _allowed[msg.sender][spender].add(addedValue);
                                            emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
                                            return true;
                                        }
                                    
                                        /**
                                         * @dev Decrease the amount of tokens that an owner allowed to a spender.
                                         * approve should be called when allowed_[_spender] == 0. To decrement
                                         * allowed value is better to use this function to avoid 2 calls (and wait until
                                         * the first transaction is mined)
                                         * From MonolithDAO Token.sol
                                         * Emits an Approval event.
                                         * @param spender The address which will spend the funds.
                                         * @param subtractedValue The amount of tokens to decrease the allowance by.
                                         */
                                        function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
                                            require(spender != address(0));
                                    
                                            _allowed[msg.sender][spender] = _allowed[msg.sender][spender].sub(subtractedValue);
                                            emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
                                            return true;
                                        }
                                    
                                        /**
                                        * @dev Transfer token for a specified addresses
                                        * @param from The address to transfer from.
                                        * @param to The address to transfer to.
                                        * @param value The amount to be transferred.
                                        */
                                        function _transfer(address from, address to, uint256 value) internal {
                                            require(to != address(0));
                                    
                                            _balances[from] = _balances[from].sub(value);
                                            _balances[to] = _balances[to].add(value);
                                            emit Transfer(from, to, value);
                                        }
                                    
                                        /**
                                         * @dev Internal function that mints an amount of the token and assigns it to
                                         * an account. This encapsulates the modification of balances such that the
                                         * proper events are emitted.
                                         * @param account The account that will receive the created tokens.
                                         * @param value The amount that will be created.
                                         */
                                        function _mint(address account, uint256 value) internal {
                                            require(account != address(0));
                                    
                                            _totalSupply = _totalSupply.add(value);
                                            _balances[account] = _balances[account].add(value);
                                            emit Transfer(address(0), account, value);
                                        }
                                    
                                        /**
                                         * @dev Internal function that burns an amount of the token of a given
                                         * account.
                                         * @param account The account whose tokens will be burnt.
                                         * @param value The amount that will be burnt.
                                         */
                                        function _burn(address account, uint256 value) internal {
                                            require(account != address(0));
                                    
                                            _totalSupply = _totalSupply.sub(value);
                                            _balances[account] = _balances[account].sub(value);
                                            emit Transfer(account, address(0), value);
                                        }
                                    
                                        /**
                                         * @dev Internal function that burns an amount of the token of a given
                                         * account, deducting from the sender's allowance for said account. Uses the
                                         * internal burn function.
                                         * Emits an Approval event (reflecting the reduced allowance).
                                         * @param account The account whose tokens will be burnt.
                                         * @param value The amount that will be burnt.
                                         */
                                        function _burnFrom(address account, uint256 value) internal {
                                            _allowed[account][msg.sender] = _allowed[account][msg.sender].sub(value);
                                            _burn(account, value);
                                            emit Approval(account, msg.sender, _allowed[account][msg.sender]);
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/access/Roles.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    /**
                                     * @title Roles
                                     * @dev Library for managing addresses assigned to a Role.
                                     */
                                    library Roles {
                                        struct Role {
                                            mapping (address => bool) bearer;
                                        }
                                    
                                        /**
                                         * @dev give an account access to this role
                                         */
                                        function add(Role storage role, address account) internal {
                                            require(account != address(0));
                                            require(!has(role, account));
                                    
                                            role.bearer[account] = true;
                                        }
                                    
                                        /**
                                         * @dev remove an account's access to this role
                                         */
                                        function remove(Role storage role, address account) internal {
                                            require(account != address(0));
                                            require(has(role, account));
                                    
                                            role.bearer[account] = false;
                                        }
                                    
                                        /**
                                         * @dev check if an account has this role
                                         * @return bool
                                         */
                                        function has(Role storage role, address account) internal view returns (bool) {
                                            require(account != address(0));
                                            return role.bearer[account];
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/access/roles/MinterRole.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    contract MinterRole {
                                        using Roles for Roles.Role;
                                    
                                        event MinterAdded(address indexed account);
                                        event MinterRemoved(address indexed account);
                                    
                                        Roles.Role private _minters;
                                    
                                        constructor () internal {
                                            _addMinter(msg.sender);
                                        }
                                    
                                        modifier onlyMinter() {
                                            require(isMinter(msg.sender));
                                            _;
                                        }
                                    
                                        function isMinter(address account) public view returns (bool) {
                                            return _minters.has(account);
                                        }
                                    
                                        function addMinter(address account) public onlyMinter {
                                            _addMinter(account);
                                        }
                                    
                                        function renounceMinter() public {
                                            _removeMinter(msg.sender);
                                        }
                                    
                                        function _addMinter(address account) internal {
                                            _minters.add(account);
                                            emit MinterAdded(account);
                                        }
                                    
                                        function _removeMinter(address account) internal {
                                            _minters.remove(account);
                                            emit MinterRemoved(account);
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    /**
                                     * @title ERC20Mintable
                                     * @dev ERC20 minting logic
                                     */
                                    contract ERC20Mintable is ERC20, MinterRole {
                                        /**
                                         * @dev Function to mint tokens
                                         * @param to The address that will receive the minted tokens.
                                         * @param value The amount of tokens to mint.
                                         * @return A boolean that indicates if the operation was successful.
                                         */
                                        function mint(address to, uint256 value) public onlyMinter returns (bool) {
                                            _mint(to, value);
                                            return true;
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    /**
                                     * @title Burnable Token
                                     * @dev Token that can be irreversibly burned (destroyed).
                                     */
                                    contract ERC20Burnable is ERC20 {
                                        /**
                                         * @dev Burns a specific amount of tokens.
                                         * @param value The amount of token to be burned.
                                         */
                                        function burn(uint256 value) public {
                                            _burn(msg.sender, value);
                                        }
                                    
                                        /**
                                         * @dev Burns a specific amount of tokens from the target address and decrements allowance
                                         * @param from address The address which you want to send tokens from
                                         * @param value uint256 The amount of token to be burned
                                         */
                                        function burnFrom(address from, uint256 value) public {
                                            _burnFrom(from, value);
                                        }
                                    }
                                    
                                    // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    /**
                                     * @title ERC20Detailed token
                                     * @dev The decimals are only for visualization purposes.
                                     * All the operations are done using the smallest and indivisible token unit,
                                     * just as on Ethereum all the operations are done in wei.
                                     */
                                    contract ERC20Detailed is IERC20 {
                                        string private _name;
                                        string private _symbol;
                                        uint8 private _decimals;
                                    
                                        constructor (string memory name, string memory symbol, uint8 decimals) public {
                                            _name = name;
                                            _symbol = symbol;
                                            _decimals = decimals;
                                        }
                                    
                                        /**
                                         * @return the name of the token.
                                         */
                                        function name() public view returns (string memory) {
                                            return _name;
                                        }
                                    
                                        /**
                                         * @return the symbol of the token.
                                         */
                                        function symbol() public view returns (string memory) {
                                            return _symbol;
                                        }
                                    
                                        /**
                                         * @return the number of decimals of the token.
                                         */
                                        function decimals() public view returns (uint8) {
                                            return _decimals;
                                        }
                                    }
                                    
                                    // File: contracts/robonomics/XRT.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    
                                    contract XRT is ERC20Mintable, ERC20Burnable, ERC20Detailed {
                                        constructor(uint256 _initial_supply) public ERC20Detailed("Robonomics", "XRT", 9) {
                                            _mint(msg.sender, _initial_supply);
                                        }
                                    }
                                    
                                    // File: contracts/robonomics/Liability.sol
                                    
                                    pragma solidity ^0.5.0;
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    contract Liability is ILiability {
                                        using ECDSA for bytes32;
                                        using SafeERC20 for XRT;
                                        using SafeERC20 for ERC20;
                                    
                                        address public factory;
                                        XRT     public xrt;
                                    
                                        function setup(XRT _xrt) external returns (bool) {
                                            require(factory == address(0));
                                    
                                            factory = msg.sender;
                                            xrt     = _xrt;
                                    
                                            return true;
                                        }
                                    
                                        function demand(
                                            bytes   calldata _model,
                                            bytes   calldata _objective,
                                    
                                            address _token,
                                            uint256 _cost,
                                    
                                            address _lighthouse,
                                    
                                            address _validator,
                                            uint256 _validator_fee,
                                    
                                            uint256 _deadline,
                                            address _sender,
                                            bytes   calldata _signature
                                        )
                                            external
                                            returns (bool)
                                        {
                                            require(msg.sender == factory);
                                            require(block.number < _deadline);
                                    
                                            model        = _model;
                                            objective    = _objective;
                                            token        = _token;
                                            cost         = _cost;
                                            lighthouse   = _lighthouse;
                                            validator    = _validator;
                                            validatorFee = _validator_fee;
                                    
                                            demandHash = keccak256(abi.encodePacked(
                                                _model
                                              , _objective
                                              , _token
                                              , _cost
                                              , _lighthouse
                                              , _validator
                                              , _validator_fee
                                              , _deadline
                                              , IFactory(factory).nonceOf(_sender)
                                              , _sender
                                            ));
                                    
                                            promisee = demandHash
                                                .toEthSignedMessageHash()
                                                .recover(_signature);
                                            require(promisee == _sender);
                                            return true;
                                        }
                                    
                                        function offer(
                                            bytes   calldata _model,
                                            bytes   calldata _objective,
                                            
                                            address _token,
                                            uint256 _cost,
                                    
                                            address _validator,
                                    
                                            address _lighthouse,
                                            uint256 _lighthouse_fee,
                                    
                                            uint256 _deadline,
                                            address _sender,
                                            bytes   calldata _signature
                                        )
                                            external
                                            returns (bool)
                                        {
                                            require(msg.sender == factory);
                                            require(block.number < _deadline);
                                            require(keccak256(model) == keccak256(_model));
                                            require(keccak256(objective) == keccak256(_objective));
                                            require(_token == token);
                                            require(_cost == cost);
                                            require(_lighthouse == lighthouse);
                                            require(_validator == validator);
                                    
                                            lighthouseFee = _lighthouse_fee;
                                    
                                            offerHash = keccak256(abi.encodePacked(
                                                _model
                                              , _objective
                                              , _token
                                              , _cost
                                              , _validator
                                              , _lighthouse
                                              , _lighthouse_fee
                                              , _deadline
                                              , IFactory(factory).nonceOf(_sender)
                                              , _sender
                                            ));
                                    
                                            promisor = offerHash
                                                .toEthSignedMessageHash()
                                                .recover(_signature);
                                            require(promisor == _sender);
                                            return true;
                                        }
                                    
                                        function finalize(
                                            bytes calldata _result,
                                            bool  _success,
                                            bytes calldata _signature
                                        )
                                            external
                                            returns (bool)
                                        {
                                            require(msg.sender == lighthouse);
                                            require(!isFinalized);
                                    
                                            isFinalized = true;
                                            result      = _result;
                                            isSuccess   = _success;
                                    
                                            address resultSender = keccak256(abi.encodePacked(this, _result, _success))
                                                .toEthSignedMessageHash()
                                                .recover(_signature);
                                    
                                            if (validator == address(0)) {
                                                require(resultSender == promisor);
                                            } else {
                                                require(IValidator(validator).isValidator(resultSender));
                                                // Transfer validator fee when is set
                                                if (validatorFee > 0)
                                                    xrt.safeTransfer(validator, validatorFee);
                                    
                                            }
                                    
                                            if (cost > 0)
                                                ERC20(token).safeTransfer(isSuccess ? promisor : promisee, cost);
                                    
                                            emit Finalized(isSuccess, result);
                                            return true;
                                        }
                                    }