Spaces:
Runtime error
Runtime error
/** | |
*Submitted for verification at Etherscan.io on 2018-01-17 | |
*/ | |
pragma solidity ^0.4.19; | |
/** | |
* @title IDXM Contract. IDEX Membership Token contract. | |
* | |
* @author Ray Pulver, [email protected] | |
*/ | |
interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; } | |
contract SafeMath { | |
function safeMul(uint256 a, uint256 b) returns (uint256) { | |
uint256 c = a * b; | |
require(a == 0 || c / a == b); | |
return c; | |
} | |
function safeSub(uint256 a, uint256 b) returns (uint256) { | |
require(b <= a); | |
return a - b; | |
} | |
function safeAdd(uint256 a, uint256 b) returns (uint256) { | |
uint c = a + b; | |
require(c >= a && c >= b); | |
return c; | |
} | |
} | |
contract Owned { | |
address public owner; | |
function Owned() { | |
owner = msg.sender; | |
} | |
function setOwner(address _owner) returns (bool success) { | |
owner = _owner; | |
return true; | |
} | |
modifier onlyOwner { | |
require(msg.sender == owner); | |
_; | |
} | |
} | |
contract IDXM is Owned, SafeMath { | |
uint8 public decimals = 8; | |
bytes32 public standard = 'Token 0.1'; | |
bytes32 public name = 'IDEX Membership'; | |
bytes32 public symbol = 'IDXM'; | |
uint256 public totalSupply; | |
event Approval(address indexed from, address indexed spender, uint256 amount); | |
mapping (address => uint256) public balanceOf; | |
mapping (address => mapping (address => uint256)) public allowance; | |
event Transfer(address indexed from, address indexed to, uint256 value); | |
uint256 public baseFeeDivisor; | |
uint256 public feeDivisor; | |
uint256 public singleIDXMQty; | |
function () external { | |
throw; | |
} | |
uint8 public feeDecimals = 8; | |
struct Validity { | |
uint256 last; | |
uint256 ts; | |
} | |
mapping (address => Validity) public validAfter; | |
uint256 public mustHoldFor = 604800; | |
mapping (address => uint256) public exportFee; | |
/** | |
* Constructor. | |
* | |
*/ | |
function IDXM() { | |
totalSupply = 200000000000; | |
balanceOf[msg.sender] = totalSupply; | |
exportFee[0x00000000000000000000000000000000000000ff] = 100000000; | |
precalculate(); | |
} | |
bool public balancesLocked = false; | |
function uploadBalances(address[] addresses, uint256[] balances) onlyOwner { | |
require(!balancesLocked); | |
require(addresses.length == balances.length); | |
uint256 sum; | |
for (uint256 i = 0; i < uint256(addresses.length); i++) { | |
sum = safeAdd(sum, safeSub(balances[i], balanceOf[addresses[i]])); | |
balanceOf[addresses[i]] = balances[i]; | |
} | |
balanceOf[owner] = safeSub(balanceOf[owner], sum); | |
} | |
function lockBalances() onlyOwner { | |
balancesLocked = true; | |
} | |
/** | |
* @notice Transfer `_amount` from `msg.sender.address()` to `_to`. | |
* | |
* @param _to Address that will receive. | |
* @param _amount Amount to be transferred. | |
*/ | |
function transfer(address _to, uint256 _amount) returns (bool success) { | |
require(!locked); | |
require(balanceOf[msg.sender] >= _amount); | |
require(balanceOf[_to] + _amount >= balanceOf[_to]); | |
balanceOf[msg.sender] -= _amount; | |
uint256 preBalance = balanceOf[_to]; | |
balanceOf[_to] += _amount; | |
bool alreadyMax = preBalance >= singleIDXMQty; | |
if (!alreadyMax) { | |
if (now >= validAfter[_to].ts + mustHoldFor) validAfter[_to].last = preBalance; | |
validAfter[_to].ts = now; | |
} | |
if (validAfter[msg.sender].last > balanceOf[msg.sender]) validAfter[msg.sender].last = balanceOf[msg.sender]; | |
Transfer(msg.sender, _to, _amount); | |
return true; | |
} | |
/** | |
* @notice Transfer `_amount` from `_from` to `_to`. | |
* | |
* @param _from Origin address | |
* @param _to Address that will receive | |
* @param _amount Amount to be transferred. | |
* @return result of the method call | |
*/ | |
function transferFrom(address _from, address _to, uint256 _amount) returns (bool success) { | |
require(!locked); | |
require(balanceOf[_from] >= _amount); | |
require(balanceOf[_to] + _amount >= balanceOf[_to]); | |
require(_amount <= allowance[_from][msg.sender]); | |
balanceOf[_from] -= _amount; | |
uint256 preBalance = balanceOf[_to]; | |
balanceOf[_to] += _amount; | |
allowance[_from][msg.sender] -= _amount; | |
bool alreadyMax = preBalance >= singleIDXMQty; | |
if (!alreadyMax) { | |
if (now >= validAfter[_to].ts + mustHoldFor) validAfter[_to].last = preBalance; | |
validAfter[_to].ts = now; | |
} | |
if (validAfter[_from].last > balanceOf[_from]) validAfter[_from].last = balanceOf[_from]; | |
Transfer(_from, _to, _amount); | |
return true; | |
} | |
/** | |
* @notice Approve spender `_spender` to transfer `_amount` from `msg.sender.address()` | |
* | |
* @param _spender Address that receives the cheque | |
* @param _amount Amount on the cheque | |
* @param _extraData Consequential contract to be executed by spender in same transcation. | |
* @return result of the method call | |
*/ | |
function approveAndCall(address _spender, uint256 _amount, bytes _extraData) returns (bool success) { | |
tokenRecipient spender = tokenRecipient(_spender); | |
if (approve(_spender, _amount)) { | |
spender.receiveApproval(msg.sender, _amount, this, _extraData); | |
return true; | |
} | |
} | |
/** | |
* @notice Approve spender `_spender` to transfer `_amount` from `msg.sender.address()` | |
* | |
* @param _spender Address that receives the cheque | |
* @param _amount Amount on the cheque | |
* @return result of the method call | |
*/ | |
function approve(address _spender, uint256 _amount) returns (bool success) { | |
require(!locked); | |
allowance[msg.sender][_spender] = _amount; | |
Approval(msg.sender, _spender, _amount); | |
return true; | |
} | |
function setExportFee(address addr, uint256 fee) onlyOwner { | |
require(addr != 0x00000000000000000000000000000000000000ff); | |
exportFee[addr] = fee; | |
} | |
function setHoldingPeriod(uint256 ts) onlyOwner { | |
mustHoldFor = ts; | |
} | |
/* --------------- fee calculation method ---------------- */ | |
/** | |
* @notice 'Returns the fee for a transfer from `from` to `to` on an amount `amount`. | |
* | |
* Fee's consist of a possible | |
* - import fee on transfers to an address | |
* - export fee on transfers from an address | |
* IDXM ownership on an address | |
* - reduces fee on a transfer from this address to an import fee-ed address | |
* - reduces the fee on a transfer to this address from an export fee-ed address | |
* IDXM discount does not work for addresses that have an import fee or export fee set up against them. | |
* | |
* IDXM discount goes up to 100% | |
* | |
* @param from From address | |
* @param to To address | |
* @param amount Amount for which fee needs to be calculated. | |
* | |
*/ | |
function feeFor(address from, address to, uint256 amount) constant external returns (uint256 value) { | |
uint256 fee = exportFee[from]; | |
if (fee == 0) return 0; | |
uint256 amountHeld; | |
if (balanceOf[to] != 0) { | |
if (validAfter[to].ts + mustHoldFor < now) amountHeld = balanceOf[to]; | |
else amountHeld = validAfter[to].last; | |
if (amountHeld >= singleIDXMQty) return 0; | |
return amount*fee*(singleIDXMQty - amountHeld) / feeDivisor; | |
} else return amount*fee / baseFeeDivisor; | |
} | |
bool public locked = true; | |
function unlockToken() onlyOwner { | |
locked = false; | |
} | |
function precalculate() internal returns (bool success) { | |
baseFeeDivisor = pow10(1, feeDecimals); | |
feeDivisor = pow10(1, feeDecimals + decimals); | |
singleIDXMQty = pow10(1, decimals); | |
} | |
function div10(uint256 a, uint8 b) internal returns (uint256 result) { | |
for (uint8 i = 0; i < b; i++) { | |
a /= 10; | |
} | |
return a; | |
} | |
function pow10(uint256 a, uint8 b) internal returns (uint256 result) { | |
for (uint8 i = 0; i < b; i++) { | |
a *= 10; | |
} | |
return a; | |
} | |
} |