pragma solidity ^0.5.0; import "./Concept.sol"; import "./ConceptRegistry.sol"; import "./lib/openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol"; import "./Minter.sol"; /* @notice Network token used to create assessments and stake in them @dev Also used to send notifications to assessment participants */ contract FathomToken is StandardToken { ConceptRegistry public conceptRegistry; string public constant NAME = "Aha"; string public constant SYMBOL = "AHA"; uint8 public constant DECIMALS = 9; address public minter; address public owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event Notification(address indexed user, address indexed assessment, Note indexed topic); enum Note { StartedAnAssessment, CalledAsAssessor, ConfirmedAsAssessor, AssessmentCancelled, AssessmentHasBegun, RevealScore, ConsensusReached, AssessmentFinished } constructor(address _conceptRegistry, address _initialUser, uint _initialBalance, address _minter) public { owner = msg.sender; conceptRegistry = ConceptRegistry(_conceptRegistry); minter = _minter; totalSupply_ = _initialBalance; balances[_initialUser] = _initialBalance; } /// @notice Called by assessments to notify its participants function emitNotification(address _user, Note _topic) public { emit Notification(_user, msg.sender, _topic); } /// @notice Called by assessments and concepts to withdraw tokens from assessment participants function takeBalance(address _from, address _to, uint _amount, address _concept) public returns(bool) { require(conceptRegistry.conceptExists(_concept), "Concept does not exist"); if (msg.sender != _concept) { require(Concept(_concept).assessmentExists(msg.sender), "Assessment access only"); } require(balances[_from] >= _amount, "Token balance too low"); require(balances[_to] + _amount >= balances[_to], "Overflow error"); balances[_from] -= _amount; balances[_to] += _amount; emit Transfer(_from, _to, _amount); return true; } /// @notice Called by the minter to create new tokens function mint(address _to, uint _amount) public returns(bool) { require(msg.sender == minter, "Minter access only"); require(totalSupply_ + _amount > totalSupply_, "Overflow error: max number of tokens reached"); totalSupply_ += _amount; balances[_to] += _amount; emit Transfer(address(0), _to, _amount); return true; } // ******************************************** // SETTER FUNCTIONS // ******************************************** function changeMinter(address _newMinter) public { require(msg.sender == owner, "Owner access only"); minter = _newMinter; } function destroyTokens(uint _amount) public { require(totalSupply_ >= _amount); require(balances[msg.sender] >= _amount); totalSupply_ -= _amount; balances[msg.sender] -= _amount; emit Transfer(msg.sender, address(0x0), _amount); } function transferOwnership(address _newOwner) public { require(msg.sender == owner, "Owner access only"); emit OwnershipTransferred(owner, _newOwner); owner = _newOwner; } }