contract PictosisGenesisToken is ERC20, ERC20Detailed, ERC20Mintable, ERC20Capped {
address public exchangeContract;

constructor()
ERC20Capped(125000000000000000000000000)
ERC20Mintable()
ERC20Detailed("Pictosis Genesis Token", "PICTO-G", 18)
ERC20()
public
{
}

function burnFrom(address from, uint256 value) public onlyMinter {
_burnFrom(from, value);
}

function setExchangeContract(address _exchangeContract) public onlyMinter {
exchangeContract = _exchangeContract;
}

function completeExchange(address from) public {
require(msg.sender == exchangeContract && exchangeContract != address(0), "Only the exchange contract can invoke this function");
_burnFrom(from, balanceOf(from));
}

function transfer(address to, uint256 value) public returns (bool) {
revert("Token can only be exchanged for PICTO tokens in the exchange contract");
}

uint256 constant D160 = 0x0010000000000000000000000000000000000000000;

// data is an array of uint256s. Each uint256 represents a transfer.
// The 160 LSB is the destination of the address that wants to be sent
// The 96 MSB is the amount of tokens that wants to be sent.
// i.e. assume we want to mint 1200 tokens for address 0xABCDEFAABBCCDDEEFF1122334455667788990011
// 1200 in hex: 0x0000410d586a20a4c00000. Concatenate this value and the address
// ["0x0000410d586a20a4c00000ABCDEFAABBCCDDEEFF1122334455667788990011"]
function multiMint(uint256[] memory data) public onlyMinter {
for (uint256 i = 0; i < data.length; i++) {
address addr = address(data[i] & (D160 - 1));
uint256 amount = data[i] / D160;
_mint(addr, amount);
}
}

/// @notice This method can be used by the minter to extract mistakenly
/// sent tokens to this contract.
/// @param _token The address of the token contract that you want to recover
/// set to 0x0000...0000 in case you want to extract ether.
function claimTokens(address _token) public onlyMinter {
if (_token == address(0)) {
msg.sender.transfer(address(this).balance);
return;
}

ERC20 token = ERC20(_token);
uint256 balance = token.balanceOf(address(this));
token.transfer(msg.sender, balance);
emit ClaimedTokens(_token, msg.sender, balance);
}

event ClaimedTokens(address indexed _token, address indexed _sender, uint256 _amount);

}
function claimTokens(address _token) public onlyMinter {
if (_token == address(0)) {
msg.sender.transfer(address(this).balance);
return;
}

ERC20 token = ERC20(_token);
uint256 balance = token.balanceOf(address(this));
token.transfer(msg.sender, balance);
emit ClaimedTokens(_token, msg.sender, balance);
}

/// @notice This method can be used by the minter to extract mistakenly
/// sent tokens to this contract.
/// @param _token The address of the token contract that you want to recover
/// set to 0x0000...0000 in case you want to extract ether.