I'm a newbie trying to make a crowdsale contract in Ropsten (deployed a token contract very well before) but i meet some problems :
I can't send ether to crowdsale contract, returning a fail status and "cancelled" (Here's an exemple 0xc0f742937d935200f8ea22f430a942c2291f3154c733025dcad88f2b0c7042b0 )
When i compiled in Remix i had
Fallback function of contract TokenCrowdsale requires too much gas (infinite)
and
Gas requirement of function TokenCrowdsale.Buytokens() high: infinite
(and for all other TokenCrowdsale functions).
Because of this "infinite gas cost" i can't interact with deployed crowdsale...
I use metamask
Crowdsale code :
pragma solidity ^0.4.20; library SafeMath { function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; assert(c / a == b); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { // assert(b > 0); // Solidity automatically throws when dividing by 0 uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; assert(c >= a); return c; } } contract Ownable { address public owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); function Ownable() public { owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner); _; } function transferOwnership(address newOwner) public onlyOwner { require(newOwner != address(0)); OwnershipTransferred(owner, newOwner); owner = newOwner; } } contract PausableToken is Ownable { function balanceOf(address who) public constant returns (uint256); function transfer(address to, uint256 value) public returns (bool); function increaseFrozen(address _owner,uint256 _incrementalAmount) public returns (bool); function burn(uint256 _value) public; } contract TokenCrowdsale is Ownable { using SafeMath for uint256; PausableToken public tokenReward; // address of the token used as reward // deployment variables for static supply sale uint256 public initialSupply; uint256 public tokensRemaining; uint256 public decimals; // multi-sig addresses and price variable address public beneficiaryWallet; // beneficiaryMultiSig (founder group) or wallet account uint256 public tokensPerEthPrice; // set initial value floating priceVar 1,000 tokens per Eth // uint256 values for min,max,caps,tracking uint256 public amountRaisedInWei; uint256 public fundingMinCapInWei; // pricing veriable uint256 public p1_duration; uint256 public p2_start; // loop control, ICO startup and limiters uint256 public fundingStartTime; // crowdsale start time# uint256 public fundingEndTime; // crowdsale end time# bool public isCrowdSaleClosed = false; // crowdsale completion boolean bool public areFundsReleasedToBeneficiary = false; // boolean for founder to receive Eth or not bool public isCrowdSaleSetup = false; // boolean for crowdsale setup event Buy(address indexed _sender, uint256 _eth, uint256 _LOL); event Refund(address indexed _refunder, uint256 _value); event Burn(address _from, uint256 _value); mapping(address => uint256) fundValue; // convert tokens to decimals function toPony(uint256 amount) public constant returns (uint256) { return amount.mul(10**decimals); } // convert tokens to whole function toHorse(uint256 amount) public constant returns (uint256) { return amount.div(10**decimals); } // setup the CrowdSale parameters function setupCrowdsale(uint256 _fundingStartTime) external onlyOwner { if ((!(isCrowdSaleSetup)) && (!(beneficiaryWallet > 0))){ // init addresses tokenReward = PausableToken(0x39B2F057CACdd24663c60bDfD16A609e928D61A3); beneficiaryWallet = 0x63695289007Ea8Ab78106adc541a0CbF5865c816; tokensPerEthPrice = 1000; // funding targets fundingMinCapInWei = 1 ether; //1 Eth (min cap, very low we know) - crowdsale is considered success after this value // update values decimals = 18; amountRaisedInWei = 0; initialSupply = toPony(1500000); // 1,5 million * 18 decimal for 2 million tokens tokensRemaining = initialSupply; fundingStartTime = _fundingStartTime; p1_duration = 3 days; p2_start = fundingStartTime + p1_duration; fundingEndTime = p2_start + 12 days; // configure crowdsale isCrowdSaleSetup = true; isCrowdSaleClosed = false; } } function setBonusPrice() public constant returns (uint256 bonus) { require(isCrowdSaleSetup); require(fundingStartTime + p1_duration <= p2_start ); if (now >= fundingStartTime && now <= fundingStartTime + p1_duration) { // Phase-1 UltraBonus +100% = 2,000 TOK = 1 ETH bonus = 1000; } else if (now > p2_start && now <= p2_start + 1 days ) { // Phase-2 day-1 MidBonus +50% = 1,500 TOK = 1 ETH bonus = 500; } else if (now > p2_start + 1 days && now <= p2_start + 3 days - 1 days) { // Phase-2 Bonus +20% = 1,200 TOK = 1 ETH bonus = 200; } else if (now > p2_start + 3 days && now <= p2_start + 6 days ) { // Phase-2 Bonus +10% = 1,100 TOK = 1 ETH bonus = 100; } else if (now > p2_start + 6 days && now <= fundingEndTime ) { // Phase-2 week-3& week-4 Bonus +0% = 1,000 TOK = 1 ETH bonus = 0; } else { revert(); } } function updateDuration(uint256 _newP1Duration, uint256 _newP2Start) external onlyOwner{ // function to update the duration of phase-1 and adjust the start time of phase-2 require( isCrowdSaleSetup && !(p1_duration == _newP1Duration) && !(p2_start == _newP2Start) && (now < fundingStartTime + p1_duration) && (now < fundingStartTime + _newP1Duration) && (fundingStartTime + _newP1Duration < _newP2Start)); p1_duration = _newP1Duration; p2_start = _newP2Start; fundingEndTime = p2_start + 12 days; } // default payable function when sending ether to this contract function () external payable { require(msg.data.length == 0); Buytokens(); } function Buytokens() public payable { // conditions (length, crowdsale setup, zero check, exceed funding contrib check, contract valid check, within funding block range check, balance overflow check etc) require(!(msg.value == 0) && (isCrowdSaleSetup) && (now >= fundingStartTime) && (now <= fundingEndTime) && (tokensRemaining > 0)); uint256 rewardTransferAmount = 0; uint256 rewardBaseTransferAmount = 0; uint256 rewardBonusTransferAmount = 0; uint256 contributionInWei = msg.value; uint256 refundInWei = 0; rewardBonusTransferAmount = setBonusPrice(); rewardBaseTransferAmount = (msg.value.mul(tokensPerEthPrice)); // Since both ether and token have 18 decimals, No need of conversion rewardBonusTransferAmount = (msg.value.mul(rewardBonusTransferAmount)); // Since both ether and token have 18 decimals, No need of conversion rewardTransferAmount = rewardBaseTransferAmount.add(rewardBonusTransferAmount); if (rewardTransferAmount > tokensRemaining) { uint256 partialPercentage; partialPercentage = tokensRemaining.mul(10**18).div(rewardTransferAmount); contributionInWei = contributionInWei.mul(partialPercentage).div(10**18); rewardBonusTransferAmount = rewardBonusTransferAmount.mul(partialPercentage).div(10**18); rewardTransferAmount = tokensRemaining; refundInWei = msg.value.sub(contributionInWei); } amountRaisedInWei = amountRaisedInWei.add(contributionInWei); tokensRemaining = tokensRemaining.sub(rewardTransferAmount); // will cause throw if attempt to purchase over the token limit in one tx or at all once limit reached fundValue[msg.sender] = fundValue[msg.sender].add(contributionInWei); assert(tokenReward.increaseFrozen(msg.sender, rewardBonusTransferAmount)); tokenReward.transfer(msg.sender, rewardTransferAmount); Buy(msg.sender, contributionInWei, rewardTransferAmount); if (refundInWei > 0) { msg.sender.transfer(refundInWei); } } function beneficiaryMultiSigWithdraw() external onlyOwner { checkGoalReached(); require(areFundsReleasedToBeneficiary && (amountRaisedInWei >= fundingMinCapInWei)); beneficiaryWallet.transfer(this.balance); } function checkGoalReached() public returns (bytes32 response) { // return crowdfund status to owner for each result case, update public constant // update state & status variables require (isCrowdSaleSetup); if ((amountRaisedInWei < fundingMinCapInWei) && (block.timestamp <= fundingEndTime && block.timestamp >= fundingStartTime)) { // ICO in progress, under softcap areFundsReleasedToBeneficiary = false; isCrowdSaleClosed = false; return "In progress (Eth < Softcap)"; } else if ((amountRaisedInWei < fundingMinCapInWei) && (block.timestamp < fundingStartTime)) { // ICO has not started areFundsReleasedToBeneficiary = false; isCrowdSaleClosed = false; return "Crowdsale is setup"; } else if ((amountRaisedInWei < fundingMinCapInWei) && (block.timestamp > fundingEndTime)) { // ICO ended, under softcap areFundsReleasedToBeneficiary = false; isCrowdSaleClosed = true; return "Unsuccessful (Eth < Softcap)"; } else if ((amountRaisedInWei >= fundingMinCapInWei) && (tokensRemaining == 0)) { // ICO ended, all tokens gone areFundsReleasedToBeneficiary = true; isCrowdSaleClosed = true; return "Successful (LOL >= Hardcap)!"; } else if ((amountRaisedInWei >= fundingMinCapInWei) && (block.timestamp > fundingEndTime) && (tokensRemaining > 0)) { // ICO ended, over softcap! areFundsReleasedToBeneficiary = true; isCrowdSaleClosed = true; return "Successful (Eth >= Softcap)!"; } else if ((amountRaisedInWei >= fundingMinCapInWei) && (tokensRemaining > 0) && (block.timestamp <= fundingEndTime)) { // ICO in progress, over softcap! areFundsReleasedToBeneficiary = true; isCrowdSaleClosed = false; return "In progress (Eth >= Softcap)!"; } } function refund() external { // any contributor can call this to have their Eth returned. user's purchased tokens are burned prior refund of Eth. checkGoalReached(); //require minCap not reached require ((amountRaisedInWei < fundingMinCapInWei) && (isCrowdSaleClosed) && (now > fundingEndTime) && (fundValue[msg.sender] > 0)); //burn user's token balance, refund Eth sent uint256 ethRefund = fundValue[msg.sender]; fundValue[msg.sender] = 0; Burn(msg.sender, fundValue[msg.sender]); //send Eth back, burn tokens msg.sender.transfer(ethRefund); Refund(msg.sender, ethRefund); } function burnRemainingTokens() onlyOwner external { // require(now > fundingEndTime); uint256 tokensToBurn = tokenReward.balanceOf(this); tokenReward.burn(tokensToBurn); } }
I really need some help ^^