I'm trying to implement smart contract for crowd sale and faced following problem.
Firstly, I created test token here on Ethereum- using examples from OpenZeppelin framework and test CrowdSale contract using example from ethereum.org/crowdsale, source code follows. Then in Rinkeby test network:
- Deployed token contract
- Deployed token sale contract with target equals 1 ether, duration 10 minutes with link to my test token as reward token
- From two test accounts transfered 0.4 and 0.6 ether to token sale contract
- From main account send 500 tokens to crowd sale account
- From contract creator account after crowdsale withdrawed using function safeWithdrawal 0.6 + 0.4 = 1 ether
- From test two account tried to withdraw tokens but get error as on screenshot - "It seems this transaction will fail. If you submit it, it may consume all the gas you provide".
Could anybody help me to find to fix it?
P.S.: Here is source code of crowd sale contract:
pragma solidity ^0.4.2;
contract token { function transfer(address, uint256){ } }
contract DVFooCrowdsale5 {
address public beneficiary;
uint public fundingGoal;
uint public amountRaised;
uint public deadline;
// uint public price;
uint tokensForSale;
token public tokenReward;
mapping(address => uint256) public balanceOf;
bool fundingGoalReached = false;
event GoalReached(address beneficiary, uint amountRaised);
event FundTransfer(address backer, uint amount, bool isContribution);
bool crowdsaleClosed = false;
/* data structure to hold information about campaign contributors */
/* at initialization, setup the owner */
function DVFooCrowdsale5(
address ifSuccessfulSendTo,
uint fundingGoalInEthers,
uint durationInMinutes,
// uint etherCostOfEachToken,
uint tokensForSaleCount,
token addressOfTokenUsedAsReward
) {
beneficiary = ifSuccessfulSendTo;
fundingGoal = fundingGoalInEthers * 1 ether;
deadline = now + durationInMinutes * 1 minutes;
// price = etherCostOfEachToken * 1 ether;
tokensForSale = tokensForSaleCount;
tokenReward = token(addressOfTokenUsedAsReward);
}
/* The function without name is the default function that is called whenever anyone sends funds to a contract */
function () payable {
assert(!crowdsaleClosed);
uint amount = msg.value;
balanceOf[msg.sender] += amount;
amountRaised += amount;
//tokenReward.transfer(msg.sender, amount / price);
FundTransfer(msg.sender, amount, true);
}
modifier afterDeadline() { if (now >= deadline) _; }
/* checks if the goal or time limit has been reached and ends the campaign */
function checkGoalReached() afterDeadline {
if (amountRaised >= fundingGoal){
fundingGoalReached = true;
GoalReached(beneficiary, amountRaised);
}
crowdsaleClosed = true;
}
function safeWithdrawal() afterDeadline {
uint256 amount;
if (!fundingGoalReached) {
amount = balanceOf[msg.sender];
balanceOf[msg.sender] = 0;
if (amount > 0) {
if (msg.sender.send(amount)) {
FundTransfer(msg.sender, amount, false);
} else {
balanceOf[msg.sender] = amount;
}
}
}
if (fundingGoalReached && beneficiary == msg.sender) {
if (beneficiary.send(amountRaised)) {
FundTransfer(beneficiary, amountRaised, false);
} else {
//If we fail to send the funds to beneficiary, unlock funders balance
fundingGoalReached = false;
}
}
else if (fundingGoalReached)
{
amount = balanceOf[msg.sender];
balanceOf[msg.sender] = 0;
uint256 toSend = 1 ether * amount / amountRaised * tokensForSale;
tokenReward.transfer(msg.sender, toSend);
}
}
}