I have an ERC20 smart contract that allocates tokens to each user based on the amount of Ether it receives. I have added explicit checks to ensure any transaction with msg.value < the minimum token price are rejected.
My minimum token price is 1 finney. Now when I send an amount of 0.0001 to the smart contract. I expect the transaction to fail. However this doesn't seem to happen. Is this a bug with Solidity precision? Or am I doing something wrong?
My code is as follows:
pragma solidity ^0.4.11;
import './TeamAllocation.sol';
import './UnsoldAllocation.sol';
import './zeppelin/SafeMath.sol';
import './zeppelin/token/StandardToken.sol';
import './zeppelin/ownership/Ownable.sol';
contract Token is StandardToken, Ownable {
using SafeMath for uint;
string public constant name = "SAMPLE";
string public constant symbol = "SMP";
uint public constant decimals = 18;
TeamAllocation teamAllocation;
UnsoldAllocation unsoldTokens;
// Funding amount in Finney
uint public constant tokenPrice = 1 finney;
// Multisigwallet where the proceeds will be stored.
address public tokenFactory;
// Multisigwallet to unsold tokens
address public futureSale;
// Sale Period
uint public salePeriod;
uint fundingStartBlock;
uint fundingStopBlock;
// flags whether ICO is afoot.
bool fundingMode = true;
//total used tokens
uint totalUsedTokens;
event Refund(address indexed _from,uint256 _value);
event Migrate(address indexed _from, address indexed _to, uint256 _value);
modifier isNotFundable() {
if (fundingMode) throw;
_;
}
modifier isFundable() {
if (!fundingMode) throw;
_;
}
function Token(address _tokenFactory, uint256 _fundingStartBlock, uint256 _fundingStopBlock, address _icedWallet) {
salePeriod = now.add(60 hours);
tokenFactory = _tokenFactory;
fundingStartBlock = _fundingStartBlock;
fundingStopBlock = _fundingStopBlock;
totalUsedTokens = 0;
totalSupply = 800000000;
futureSale = _icedWallet;
}
function pause() onlyOwner isFundable external returns (bool) {
fundingMode = false;
}
function() payable isFundable external {
if(now > salePeriod) throw;
if(block.number < fundingStartBlock) throw;
if(block.number > fundingStopBlock) throw;
if(totalUsedTokens >= totalSupply) throw;
if (msg.value < tokenPrice) throw;
//transfer money to tokenFactory MultisigWallet
if(!tokenFactory.send(msg.value)) throw;
uint numTokens = msg.value.div(tokenPrice);
totalUsedTokens = totalUsedTokens.add(numTokens);
if (totalUsedTokens > totalSupply) throw;
balances[msg.sender] = balances[msg.sender].add(numTokens);
Transfer(0, msg.sender, numTokens);
}
//@notice Function that reports how long the sale is active
function checkSalePeriod() external constant returns (uint) {
return salePeriod;
}
//@notice Function that reports whether funding is active.
function fundingActive() constant isFundable external returns (bool){
if(block.number < fundingStartBlock || block.number > fundingStopBlock || totalUsedTokens > totalSupply){
return false;
}
return true;
}
//@notice Function reports the number of tokens available for sale
function numberOfTokensLeft() constant returns (uint256) {
if (block.number > fundingStopBlock) {
return 0;
}
uint tokensAvailableForSale = totalSupply - totalUsedTokens;
return tokensAvailableForSale;
}
function finalize() isFundable onlyOwner external {
if ((block.number <= fundingStopBlock ||
totalUsedTokens < minTokensForSale) &&
totalUsedTokens < totalSupply) throw;
if(futureSale == address(0)) throw;
// switch funding mode off
fundingMode = false;
//Allot team tokens to a smart contract which will frozen for 9 months
//transfer any balance available to Pillar Multisig Wallet
if (!tokenFactory.send(this.balance)) throw;
}
function refund() isFundable external {
if(block.number <= fundingStopBlock) throw;
if(totalUsedTokens >= minTokensForSale) throw;
uint plrValue = balances[msg.sender];
if(plrValue == 0) throw;
balances[msg.sender] = 0;
uint ethValue = plrValue.mul(tokenPrice);
if(!msg.sender.send(ethValue)) throw;
Refund(msg.sender, ethValue);
}
}
Any help will be truly appreciated.