Exhibit 4.3


 


	InxToken.sol	 








 


pragma solidity ^0.4.24;


 


import “./openzeppelin-solidity/contracts/math/SafeMath.sol”;


 


/** 


* @title INX Ownable


* @dev Extanded version of ownable, but with multiple
owners. The contract allow multiple owners


* to be set and checked.


*/


contract Ownable {


 


mapping ( address => uint) public owners;


 


event NewOwnerAdded(address _address);


 


/**


* @dev Throws if called by a none valid account.


*/


modifier onlyValidAddress(address _address) {


require(_address != address(0), “Address should
be valid”);


_;


}


 


/**





* @dev Throws if called by any account other than the
owner.


*/


modifier onlyOwner() {


require(isOwner(), “This operation requires an
owner privilages”);


_;


}


 


/**


 


* @return true if ‘msg.sender’ is the owner of the
contract.


*/


function isOwner() public view returns(bool) {


return owners[msg.sender] != 0;


}


 


/** 


* @dev Allows the current owner to add new oweners.


* @param newOwner The address to add as an owner.


*/


function addOwner(address newOwner) public
onlyValidAddress(newOwner) onlyOwner() returns (bool)


{


owners[newOwner] = 1;


emit NewOwnerAdded(newOwner);


return true;


}


 


/** 


* @dev Allows the current owner to remove owner from
the owners list control of the contract to a newOwner.


* @param ownerToRemoved The address of the owner that
should be removed.


*/


function removeOwner(address ownerToRemoved) public


onlyValidAddress(ownerToRemoved) onlyOwner() returns
(bool)


{


delete owners[ownerToRemoved];


return true;


}


}


 


/**





* @title INX Whitelisters


 







    1


     


    

 


	InxToken.sol	 


 


* @dev A similar version of Ownable list, but that
manages white lister - address that can only modify white listing.


*/


contract Whitelisters is Ownable{


 


mapping ( address => uint) public whitelisters;


 


event NewWhiteListerAdded(address _address);


event WhiteListerRemoved(address _address); 


 


/** 


* @dev Throws if called by a none valid account.


*/


modifier onlyValidAddress(address _address) {


require(_address != address(0), “Address should
be valid”);


_;


}


 


/** 


* @dev Throws if called by any account other than a
whitelister.


*/


modifier onlyWhitelister() {


require(isWhitelister(), “This operation requires
whitelister


privilages”);


_;


}


 


/** 


* @return true if ‘msg.sender’ is a whitelister of
the contract.


*/


function isWhitelister() public view returns(bool)
{


return whitelisters[msg.sender] != 0;


}


 


/** 


* @dev Allows the current owner to add new whitelister.


* @param newWhitelister The address to add as a whitelister.


*/


function addWhitelister(address newWhitelister) public


onlyValidAddress(newWhitelister) onlyOwner() returns
(bool) {


whitelisters[newWhitelister] = 1;


emit NewWhiteListerAdded(newWhitelister);


return true;


}


 


/** 


* @dev Allows the current owner to remove whitelister
from the whitelister list .


* @param whitelisterToRemoved The address of the owner
that should be removed.


*/


function removeWhitelister(address whitelisterToRemoved)
public


onlyValidAddress(whitelisterToRemoved) onlyOwner()
returns (bool) {


delete whitelisters[whitelisterToRemoved];


emit WhiteListerRemoved(whitelisterToRemoved);


return true;


}


}


 


contract Whitelisting is Ownable, Whitelisters {


 


event WhitelistUpdate(address _address,bool status,string
data);


  







    2


     


    

 


	InxToken.sol	 






 


struct whiteListItem {


 bool status;


string data;


}


 


// check for valid address 


modifier onlyValidAddress(address _address) {


require(_address != address(0), “Address should
be valid”);


_;


}


 


// white list status 


mapping (address => whiteListItem) public whitelist;


 


/** 


* @dev Set a white list address


* @param to the address to be set


* @param status the whitelisting status (true for yes,
false for no)


* @param data a string with data about the whitelisted
address


*/


function setWhitelist(address to, bool status, string
memory data)public


onlyValidAddress(to) onlyWhitelister returns(bool){


whitelist[to] = whiteListItem(status, data);


return true;


}


 


/** 


* @dev Check the status of the whitelist


* @param _address the address to be check


*/


function checkWhitelistStatus(address _address) public
view returns(bool){


return whitelist[_address].status;


}


 


/** 


* @dev Get the data of and address in the whitelist


* @param _address the address to retrieve the data
from


*/


function getWhitelistData(address _address) public
view returns(string memory)


{


return whitelist[_address].data;


}


}


 


contract Timelock is Ownable {


 


using SafeMath for uint256;


 


struct lockupItem {


 


uint256 amount;


uint256 releaseTime;


}


 


mapping (address => lockupItem) lockups;


 


event AccountLock(address _address, uint256 amount,
uint256 releaseTime);


event AccountRelease(address _address, uint256 amount);


 


/** 


* @dev lock address and amount and lock it, set the
release time


* @param _address the address to lock


* @param amount the amount to lock


* @param releaseTime of the locked amount
(in seconds since the epoch)


 







    3


     


    

 





	InxToken.sol	 





 


*/ 


function lock( address _address, uint256 amount, uint256
releaseTime)


public onlyOwner returns(uint256) {


require(releaseTime > block.timestamp);


require(_address != address(0));


 


lockupItem memory _lockupItem = lockupItem(amount,
releaseTime); 


lockups[_address] = _lockupItem;


emit AccountLock(_address, amount, releaseTime);


return block.timestamp;


}


 


/** 


* @dev release locked amount


* @param _address the address to retrieve the data
from


* @param amountToRelease the amount to check


*/


function release( address _address, uint256 amountToRelease)
public


onlyOwner returns(bool) {


require(_address != address(0));


 


uint256 _lockedAmount = lockups[_address].amount;


 


// nothing to release 


if(_lockedAmount == 0){


emit AccountRelease(_address, 0);


return;


}


 


// extract release time for re-locking 


uint256 _releaseTime = lockups[_address].releaseTime;


 


// delete the lock entry 


delete lockups[_address];


 


if(_lockedAmount >= amountToRelease){ 


uint256 newLockedAmount =_lockedAmount.sub(amountToRelease);


 


// re-lock the new locked balance 


lock(_address, newLockedAmount, _releaseTime);


emit AccountRelease(_address, amountToRelease);


} else {


emit AccountRelease(_address, 0);


}


 


//


 


}


 


/** 


* @dev check if the requested amount for transaction
is free for transter


* @param _address the address to retrieve the data
from


* @param amount the amount to check


*/


function checkNoneLockedAmount(address _address, uint256
amount, uint256 balance) public view returns(uint256)


 


{


 





// check if the address is listed in the lockups mapping 


if(lockups[_address].amount == 0) return amount;


 


// check if the lockup time has not passed (ie: 1555179440 


1893502800)


if(block.timestamp < lockups[_address].releaseTime){


 







    4


     


    

 


	InxToken.sol	 


 


// check if the address balance
is bigger than the locked amount 


if(balance > lockups[_address].amount) {


 


uint256 _noneLockedAvailableAmount = 0;


 


_noneLockedAvailableAmount = balance - 


lockups[_address].amount;


 


if( _noneLockedAvailableAmount >= amount) { 


return amount;


}


}


 


// the address balance is smaller
than the locked amount, return 


0;


return 0;


}


 


return amount;


 


}


 


/** 


* @dev get address lockup info


* @param _address the address to retrieve the data
from


* @return array of 2 uint256, release time (in seconds
since the epoch) and amount (in INX)


*/


function checkLockup(address _address) public view
returns(uint256,


uint256) {


 


// copy lockup data into memory 


lockupItem memory _lockupItem = lockups[_address];


 


return (_lockupItem.releaseTime, _lockupItem.amount);


 


}


}


 


import “./InxRegistry.sol”;


 


contract InxToken is Ownable, Whitelisters, Whitelisting, Timelock
{


 


using SafeMath for uint256;


 


string public symbol; 


string publicname;


uint8 public decimals;


uint256 private _totalSupply;


 


mapping (address => uint256) private _balances;


 


/** 


* @dev Total number of tokens in existence


*/


function totalSupply() public view returns (uint256)
{


return _totalSupply;


}


 


/** 


* @dev Token decimals


*/


function tokenDecimals() public view returns (uint8)
{


return decimals;


}


 







    5


     


    

 


	InxToken.sol	 


 


/** 


* @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];


}


 


// ERC20 private _allowed 


mapping (address => mapping (address => uint256))
private _allowed;


 


// service address 


address public serviceAddress;


 


InxRegistry private inxRegistery;


 


event InxServiceUpdate(address prevInxService, address
InxService);


event LockedAmount(address _address, uint256 executed,
uint256 requested, bool partialyExcuted);


event Approval(address indexed
owner, address indexed spender, uint256 value);


event Transfer(address indexed from, address indexed
to, uint256 value);


 


/** 


* @dev constructor


* @param registryService the address of the registry
service (validation


contruct)


*/


constructor(address registryService) public {


symbol = “INX”;


name = “INX Token”;


decimals = 18;


_totalSupply = 200000000 * 10 ** uint(decimals);


_balances[msg.sender] = _totalSupply; 


 


owners[msg.sender] = 1; 


whitelisters[msg.sender] = 1;


 


serviceAddress = registryService;


 


// set the registery service instace 


inxRegistery = InxRegistry(serviceAddress);


}


 


/** 


* @dev Update the referece the address of the validator


*/


function updateInxService(address _serviceAddress)
onlyOwner public {


address prevInxService = serviceAddress;


serviceAddress = _serviceAddress;


 


// set the registery service instace 


inxRegistery = InxRegistry(serviceAddress);


emit InxServiceUpdate(prevInxService, serviceAddress);


}


 


/**


 


* @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.


 







    6


     


    

 





	InxToken.sol	 





 


*/ 


function allowance(


address owner,


address spender


)


public


view


returns (uint256)


{


return _allowed[owner][spender];


}


 


/** 


* @dev Approve the passed address to spend the specified
amount of tokens on behalf of msg.sender.


* @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));


 


uint8 reason = 99;


 


// get the whitelist status of the INX spender 


bool _spenderWhitelistStatus = whitelist[spender].status;


 


// get the whitelist status of the INX approver 


bool _approverWhitelistStatus = whitelist[msg.sender].status;


 


// get the ownership status 


bool _isOwner = owners[msg.sender] == 1;


 


// approve validation (proxy contract) 


reason = inxRegistery.validate(msg.sender, spender,
0,


_spenderWhitelistStatus, _approverWhitelistStatus,
_isOwner,


“approve”);


 


if(reason == 0){ 


_allowed[msg.sender][spender] = value;


emit Approval(msg.sender, spender, value);


return true;


} else {


revert(“approval is not valid”);


return false;


}


}


 


/** 


* @dev Increase to the passed address the amount off
tokens that are


allowed to be spended on behalf of msg.sender.


* @param spender The address which will spend the funds.


* @param addedValue The amount of tokens to add that
can be spent.


*/


function increaseApproval(address spender, uint256
addedValue) public


returns(bool){


require(spender != address(0));


 


uint8 reason = 99;


 


// get the whitelist status of the INX spender 


bool _spenderWhitelistStatus = whitelist[spender].status;


 


// get the whitelist status of the INX approver 


bool _approverWhitelistStatus = whitelist[msg.sender].status;


 







    7


     


    

 





	InxToken.sol	 


 


// get the ownership status 


bool _isOwner = owners[msg.sender] == 1;


 


// approve validation (proxy contract) 


reason = inxRegistery.validate(msg.sender, spender,
0,


_spenderWhitelistStatus, _approverWhitelistStatus,
_isOwner,


“increaseApproval”);


 


if(reason == 0){ 


uint256 oldValue = _allowed[msg.sender][spender];


_allowed[msg.sender][spender] = oldValue.add(addedValue);


return true;


} else {


revert(“increase approval is not valid”);


return false;


}


}


 


/** 


* @dev Decrease to the passed address the amount off
tokens that are allowed to be spended on behalf of msg.sender.


* @param spender The address which will spend the funds.


* @param substractedValue The amount of
tokens to add that can be spent.


*/


function decreaseApproval(address spender, uint256
substractedValue)


public returns(bool){


require(spender != address(0));


 


uint8 reason = 99;


 


// get the whitelist status of the INX spender 


bool _spenderWhitelistStatus = whitelist[spender].status;


 


// get the whitelist status of the INX approver 


bool _approverWhitelistStatus = whitelist[msg.sender].status;


 


// get the ownership status 


bool _isOwner = owners[msg.sender] == 1;


 


// approve validation (proxy contract) 


reason = inxRegistery.validate(msg.sender, spender,
0,


_spenderWhitelistStatus, _approverWhitelistStatus,
_isOwner,


“decreaseApproval”);


 


if(reason == 0){ 


uint256 oldValue = _allowed[msg.sender][spender];


 


if(substractedValue > oldValue){ 


_allowed[msg.sender][spender] = 0;


} else {


_allowed[msg.sender][spender] =


oldValue.sub(substractedValue);


}


return true;


 


} else { 


revert(“decrease approval is not valid”);


return false;


}


  


}


 







    8


     


    

  


	InxToken.sol	 








  


/** 


* @dev Transfer tokens from one address to another


* @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)


{


require(value <= _allowed[from][msg.sender], “not
enogth allowance”);


 


uint8 reason = 99;


 


// get the whitelist status of the INX spender 


bool _spenderWhitelistStatus = whitelist[msg.sender].status;


 


// get the whitelist status of the INX approver 


bool _approverWhitelistStatus = whitelist[from].status;


 


// get the ownership status 


bool _isOwner = owners[msg.sender] == 1;


 


// approve validation (proxy contract), inorder to
be consistant, we 


use the spender (msg.sender)


reason = inxRegistery.validate(from, msg.sender, 0,


_spenderWhitelistStatus, _approverWhitelistStatus,
_isOwner,


“transferFrom”);


 


if(reason == 0){ 


// substract


_allowed[from][msg.sender] = _allowed[from]


[msg.sender].sub(value);


 


_transfer(from, to, value); 


return true;


 


} else {


 


revert(“transfer from is not valid”);


return false;


}


}


 


/** 


* @dev transfer


* @param to the address to transfer the funds to


* @param value the number of tokens to transfer


*/


function transfer(address to, uint256 value) public
returns(bool) {


return _transfer(msg.sender, to, value);


}


 


/** 


* @dev _transfer


* @param to the address to transfer the funds to


* @param value the number of tokens to transfer


*/


function _transfer(address from, address to, uint256
value) internal


 






    9


     


    

 








	InxToken.sol	 



 





returns(bool) {


require(value <= _balances[from]);


require(to != address(0));







 


uint8 reason = 99;


 


// get the whitelist status of the INX receiver 


bool _toWhitelistStatus = whitelist[to].status;


 


// get the whitelist status of the INX sender 


bool _fromWhitelistStatus = whitelist[from].status;


 


// get the ownership status 


bool _isOwner = owners[msg.sender] == 1;


 


// check lockups 


uint256 _noneLockedAmount = checkNoneLockedAmount(from,
value,


_balances[from]);


 


// check if all amount is locked 


if(_noneLockedAmount == 0) {


emit LockedAmount(from,_noneLockedAmount, value, false);


revert(“amount is locked”);


}


 


// validate transaction (proxy contract) 


reason = inxRegistery.validate(from, to, _noneLockedAmount,


_toWhitelistStatus, _fromWhitelistStatus,
_isOwner, “transfer”);


 


if(reason == 0){ 


_balances[from] = _balances[from].sub(_noneLockedAmount);


_balances[to] = _balances[to].add(_noneLockedAmount);


emit Transfer(from, to, _noneLockedAmount);


} else {


revert(“transaction is not valid”);


}


 


return reason == 0;


 


}


}


 


 


10