Exhibit 4.3 pragma solidity ^0.4.24; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "./ERC20.sol"; import "./freezable.sol"; import "./Ledger.sol"; import "./ExternalStorage.sol"; import "./Registry.sol"; import "./Library.sol"; import "./displayable.sol"; import "./configurable.sol"; import "./storable.sol"; contract Token is ERC20, freezable, displayable, configurable, IStorable { using SafeMath for uint256; using Library for address; struct allowedAddr { bool status; string details; address vettingAgent; } ITokenLedger public tokenLedger; string public storageName; string public ledgerName; address public externalStorage; address public registry; uint8 public constant decimals = 18; bool public isTokenContract = true; bool public haltPurchase; // This state is specific to the first version of the Token // token contract and the token generation event, and hence // there is no reason to persist in external storage for // future contracts. bool public allowTransfers; mapping (address => allowedAddr) public whitelistedRecipient; address[] public whitelistedRecipientForIndex; mapping (address => bool) private processedWhitelistedRecipient; uint256 public contributionMinimum; event Mint(uint256 amountMinted, uint256 totalTokens, uint256 circulationCap); event Approval(address indexed _owner, address indexed _spender, uint256 _value); event Transfer(address indexed _from, address indexed _to, uint256 _value); event WhiteList(address indexed buyer, uint256 holdCap); event ConfigChanged(uint256 buyPrice, uint256 circulationCap, uint256 balanceLimit); event CommissionCalc(uint time); event VestedTokenGrant(address indexed beneficiary, uint256 startDate, uint256 cliffDate, uint256 durationSec, uint256 fullyVestedAmount, bool isRevocable); event VestedTokenRevocation(address indexed beneficiary); event VestedTokenRelease(address indexed beneficiary, uint256 amount); event StorageUpdated(address storageAddress, address ledgerAddress); event PurchaseHalted(); event PurchaseResumed(); modifier onlyFoundation { address foundation = externalStorage.getFoundation(); require(foundation != address(0)); if (msg.sender != owner && msg.sender != foundation) revert(); _; } modifier initStorage { address ledgerAddress = Registry(registry).getStorage(ledgerName); address storageAddress = Registry(registry).getStorage(storageName); tokenLedger = ITokenLedger(ledgerAddress); externalStorage = storageAddress; _; } constructor(address _registry, string _storageName, string _ledgerName) public payable { isTokenContract = true; version = "2"; require(_registry != address(0)); storageName = _storageName; ledgerName = _ledgerName; registry = _registry; addSuperAdmin(registry); } /* This unnamed function is called whenever someone tries to send ether directly to the token contract */ function () public { revert(); // Prevents accidental sending of ether } function getLedgerNameHash() external view returns (bytes32) { return keccak256(abi.encodePacked(ledgerName)); } function getStorageNameHash() external view returns (bytes32) { return keccak256(abi.encodePacked(storageName)); } function configure( bytes32 _tokenName, bytes32 _tokenSymbol, uint256 _buyPrice, uint256 _circulationCap, uint256 _balanceLimit, address _foundation, uint8 _commissionPercent, uint8 _commissionPercentRel, uint256 _commissionDate ) public onlySuperAdmins initStorage returns (bool) { uint256 __buyPrice= externalStorage.getBuyPrice(); if (__buyPrice> 0 && __buyPrice!= _buyPrice) { require(frozenToken); } commissionPercent = _commissionPercent; commissionPercentRel = _commissionPercentRel; commissionDate = _commissionDate; externalStorage.setTokenName(_tokenName); externalStorage.setTokenSymbol(_tokenSymbol); externalStorage.setBuyPrice(_buyPrice); externalStorage.setCirculationCap(_circulationCap); externalStorage.setFoundation(_foundation); externalStorage.setBalanceLimit(_balanceLimit); emit ConfigChanged(_buyPrice, _circulationCap, _balanceLimit); return true; } function configureFromStorage() public onlySuperAdmins initStorage returns (bool) { freezeToken(true); return true; } function updateStorage(string newStorageName, string newLedgerName) public onlySuperAdmins returns (bool) { require(frozenToken); storageName = newStorageName; ledgerName = newLedgerName; configureFromStorage(); address ledgerAddress = Registry(registry).getStorage(ledgerName); address storageAddress = Registry(registry).getStorage(storageName); emit StorageUpdated(storageAddress, ledgerAddress); return true; } function name() public view returns(string) { return bytes32ToString(externalStorage.getTokenName()); } function symbol() public view returns(string) { return bytes32ToString(externalStorage.getTokenSymbol()); } function totalInCirculation() public view returns(uint256) { return tokenLedger.totalInCirculation().add(totalUnvestedAndUnreleasedTokens()); } function tokenBalanceLimit() public view returns(uint256) { return externalStorage.getBalanceLimit(); } function circulationCap() public view unlesspgraded returns(uint256) { return externalStorage.getCirculationCap(); } function foundation() public view returns(address) { return externalStorage.getFoundation(); } function totalSupply() public view returns(uint256) { return tokenLedger.totalTokens(); } function tokensAvailable() public view unlesspgraded returns(uint256) { return totalSupply().sub(totalInCirculation()); } function balanceOf(address account) public view returns (uint256) { address thisAddress = this; if (thisAddress == account) { return tokensAvailable(); } else { return tokenLedger.balanceOf(account); } } function transfer(address recipient, uint256 amount) public unlessFrozen returns (bool) { require(allowTransfers || whitelistedRecipient[recipient].status); require(amount > 0); require(!frozenAccount[recipient]); uint256 commissionAmount = getCommission(amount); uint256 _amount = amount; if(commissionAmount > 0) { _amount -= commissionAmount; tokenLedger.transfer(msg.sender, owner, commissionAmount); emit Transfer(msg.sender, owner, commissionAmount); } tokenLedger.transfer(msg.sender, recipient, _amount); emit Transfer(msg.sender, recipient, _amount); return true; } function mintTokens(uint256 mintedAmount) public onlySuperAdmins returns (bool) { uint256 _circulationCap = externalStorage.getCirculationCap(); tokenLedger.mintTokens(mintedAmount); emit Mint(mintedAmount, tokenLedger.totalTokens(), _circulationCap); emit Transfer(address(0), this, mintedAmount); return true; } function grantTokens(address recipient, uint256 amount) public onlySuperAdmins returns (bool) { require(amount <= tokensAvailable()); require(!frozenAccount[recipient]); tokenLedger.debitAccount(recipient, amount); emit Transfer(this, recipient, amount); return true; } function setHaltPurchase(bool _haltPurchase) public onlySuperAdmins returns (bool) { haltPurchase = _haltPurchase; if (_haltPurchase) { emit PurchaseHalted(); } else { emit PurchaseResumed(); } return true; } function foundationDeposit() public payable returns (bool) { return true; } function allowance(address owner, address spender) public view returns (uint256) { return externalStorage.getAllowance(owner, spender); } function transferFrom(address from, address to, uint256 value) public unlessFrozen returns (bool) { require(allowTransfers); require(!frozenAccount[from]); require(!frozenAccount[to]); require(from != msg.sender); require(value > 0); uint256 allowanceValue = allowance(from, msg.sender); require(allowanceValue >= value); tokenLedger.transfer(from, to, value); externalStorage.setAllowance(from, msg.sender, allowanceValue.sub(value)); emit Transfer(from, to, value); return true; } function approve(address spender, uint256 value) public unlessFrozen returns (bool) { require(spender != address(0)); require(!frozenAccount[spender]); require(msg.sender != spender); externalStorage.setAllowance(msg.sender, spender, value); emit Approval(msg.sender, spender, value); return true; } function increaseApproval(address spender, uint256 addedValue) public unlessFrozen returns (bool) { return approve(spender, externalStorage.getAllowance(msg.sender, spender).add(addedValue)); } function decreaseApproval(address spender, uint256 subtractedValue) public unlessFrozen returns (bool) { uint256 oldValue = externalStorage.getAllowance(msg.sender, spender); if (subtractedValue > oldValue) { return approve(spender, 0); } else { return approve(spender, oldValue.sub(subtractedValue)); } } function grantVestedTokens( address beneficiary, uint256 fullyVestedAmount, uint256 startDate, // 0 indicates start "now" uint256 cliffSec, uint256 durationSec, bool isRevocable ) public onlySuperAdmins returns(bool) { uint256 _circulationCap = externalStorage.getCirculationCap(); require(beneficiary != address(0)); require(!frozenAccount[beneficiary]); require(durationSec >= cliffSec); require(totalInCirculation().add(fullyVestedAmount) <= _circulationCap); require(fullyVestedAmount <= tokensAvailable()); uint256 _now = now; if (startDate == 0) { startDate = _now; } uint256 cliffDate = startDate.add(cliffSec); externalStorage.setVestingSchedule( beneficiary, fullyVestedAmount, startDate, cliffDate, durationSec, isRevocable ); emit VestedTokenGrant(beneficiary, startDate, cliffDate, durationSec, fullyVestedAmount, isRevocable); return true; } function revokeVesting(address beneficiary) public onlySuperAdmins returns (bool) { require(beneficiary != address(0)); externalStorage.revokeVesting(beneficiary); releaseVestedTokensForBeneficiary(beneficiary); emit VestedTokenRevocation(beneficiary); return true; } function releaseVestedTokens() public unlessFrozen returns (bool) { return releaseVestedTokensForBeneficiary(msg.sender); } function releaseVestedTokensForBeneficiary(address beneficiary) public unlessFrozen returns (bool) { require(beneficiary != address(0)); require(!frozenAccount[beneficiary]); uint256 unreleased = releasableAmount(beneficiary); if (unreleased == 0) { return true; } externalStorage.releaseVestedTokens(beneficiary); tokenLedger.debitAccount(beneficiary, unreleased); emit Transfer(this, beneficiary, unreleased); emit VestedTokenRelease(beneficiary, unreleased); return true; } function releasableAmount(address beneficiary) public view returns (uint256) { return externalStorage.releasableAmount(beneficiary); } function totalUnvestedAndUnreleasedTokens() public view returns (uint256) { return externalStorage.getTotalUnvestedAndUnreleasedTokens(); } function vestingMappingSize() public view returns (uint256) { return externalStorage.vestingMappingSize(); } function vestingBeneficiaryForIndex(uint256 index) public view returns (address) { return externalStorage.vestingBeneficiaryForIndex(index); } function vestingSchedule(address _beneficiary) public view returns (uint256 startDate, uint256 cliffDate, uint256 durationSec, uint256 fullyVestedAmount, uint256 vestedAmount, uint256 vestedAvailableAmount, uint256 releasedAmount, uint256 revokeDate, bool isRevocable) { ( startDate, cliffDate, durationSec, fullyVestedAmount, releasedAmount, revokeDate, isRevocable ) = externalStorage.getVestingSchedule(_beneficiary); vestedAmount = externalStorage.vestedAmount(_beneficiary); vestedAvailableAmount = externalStorage.vestedAvailableAmount(_beneficiary); } function setAllowTransfers(bool _allowTransfers) public onlySuperAdmins returns (bool) { allowTransfers = _allowTransfers; return true; } function setContributionMinimum(uint256 _contributionMinimum) public onlySuperAdmins returns (bool) { contributionMinimum = _contributionMinimum; return true; } function totalTransferWhitelistMapping() public view returns (uint256) { return whitelistedRecipientForIndex.length; } function setWhitelistedRecipient( address recipient, bool _allowTransfers, string details, address vettingAgent ) public onlyAdmins returns (bool) { require(recipient != address(0)); whitelistedRecipient[recipient] = allowedAddr({status: _allowTransfers, details: details, vettingAgent: vettingAgent}); if (!processedWhitelistedRecipient[recipient]) { whitelistedRecipientForIndex.push(recipient); processedWhitelistedRecipient[recipient] = true; } return true; } }
- INXI Dashboard
- Financials
- Filings
- Community Notes
-
DRS/A Filing
INX (INXI) DRS/ADraft registration statement (amended)
Filed: 1 Nov 18, 12:00am