Hi I am a newbie to the Ethereum development. I have successfully deployed a burnable, pausable, capped token contract (TC) on rinkeby test network, and was able to interact with it - minted and transferred tokens without problem.
I have now written and successfully deployed a simple Crowdsale contract (CSC) wrapping TC above on Rinkeby, but have a hard time interacting with it. I kept getting "fail" transaction after sending ETH to purchase token on Metamask, and "The contract won't allow this transaction to be executed" error on Mist error. I don't know of any good tool to debug what would have gone wrong at run time. Any help will be greatly appreciated!
After reviewing other thread and comments below, i have done the following to further debug what the issue is:
- changed coin contract to interface
- added back fallback function() to accept payment
- commented out ValidPurchase() in the buyToken function
But still no cigar. Please help!
Thank you so much for your help in advance!
The deployed Token contract (TC) can be found here: https://rinkeby.etherscan.io/address/0x8A175aE6aCBC6b90812B547719ACEfaa975987AC#code
The updated deployed Crowdsale contract (CSC) can be found here: https://rinkeby.etherscan.io/address/0x686c4f0c9be46e6b45781ecf0cc745fd9fb85dde#code
Here is the CSC code:
pragma solidity ^0.4.18;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
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 c;
}
}
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
/**
* @title Pausable
* @dev Base contract which allows children to implement an emergency stop mechanism.
*/
contract Pausable is Ownable {
event Pause();
event Unpause();
bool public paused = false;
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*/
modifier whenNotPaused() {
require(!paused);
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*/
modifier whenPaused() {
require(paused);
_;
}
/**
* @dev called by the owner to pause, triggers stopped state
*/
function pause() onlyOwner whenNotPaused public {
paused = true;
Pause();
}
/**
* @dev called by the owner to unpause, returns to normal state
*/
function unpause() onlyOwner whenPaused public {
paused = false;
Unpause();
}
}
/*******************************************************************************************
* Token contract begins
* Based on references from OpenZeppelin: https://github.com/OpenZeppelin/zeppelin-solidity
*******************************************************************************************/
interface Token {
function mint(address _to, uint256 _amount) public returns (bool);
function transferOwnership(address newOwner) public;
function finishMinting() public returns(bool);
function totalSupply() public constant returns (uint256 supply);
}
/*******************************************************************************************
* @dev IHT Crowdsale contract.
* Based on references from OpenZeppelin: https://github.com/OpenZeppelin/zeppelin-solidity
*******************************************************************************************/
contract IHTCSFiveFive is Ownable, Pausable {
using SafeMath for uint256;
/**************************************************************************
* Constants
**************************************************************************/
uint256 public constant DECIMALS = 4;
uint256 public constant MAX_TOKENS_AVAILABLE = 1 * (10**8) * (10**DECIMALS); // 100Mil IHTTokenFive total
uint256 public constant MAX_TOKENS_FOR_SALE = 35 * (10**6) * (10**DECIMALS); // 35Mil IHTTokenFive
/**************************************************************************
* Variables
**************************************************************************/
Token public token; // Deployed token being sold
uint256 public startTime; // Start and end timestamps where investments are allowed (both inclusive)
uint256 public endTime;
address public wallet; // Address where funds are collected
uint256 public rate; // # token units a buyer gets per wei
uint256 public weiRaised; // Amount of raised money in wei
bool public isFinalized = false; // Finalization
/**************************************************************************
* Events
**************************************************************************/
event RateChange(uint256 _rate);
event WalletChange(address indexed _wallet);
event EndTimeChange(uint256 _endTime);
/**
* event for token purchase logging
* @param purchaser who paid for the tokens
* @param beneficiary who got the tokens
* @param value weis paid for purchase
* @param amount amount of tokens purchased
*/
event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
event Finalized();
/**************************************************************************
* Event Implementation
**************************************************************************/
/**
* @dev Sets IHTTokenFive to Ether rate
* @param _rate defines IHTv5/ETH rate: 1 ETH = _rate * IHTTokenFive
*/
function setRate(uint256 _rate) external onlyOwner {
require(_rate != 0x0);
rate = _rate;
RateChange(_rate);
}
/**
* @dev Allows to adjust the crowdsale end time
*/
function setEndTime(uint256 _endTime) external onlyOwner {
require(!isFinalized);
require(_endTime >= startTime);
require(_endTime >= now);
endTime = _endTime;
EndTimeChange(_endTime);
}
/**
* @dev Sets the wallet to forward ETH collected funds
*/
function setWallet(address _wallet) external onlyOwner {
require(_wallet != 0x0);
wallet = _wallet;
WalletChange(_wallet);
}
/**************************************************************************
* Constructor
**************************************************************************/
/**
* @dev Contructor
* @param _startTime startTime of crowdsale
* @param _endTime endTime of crowdsale
* @param _rate IHT / ETH rate
* @param _wallet wallet to forward the collected funds
* @param _token token contract to link to this crowdsale contract
*/
function IHTCSFiveFive(
uint256 _startTime,
uint256 _endTime,
uint256 _rate,
address _wallet,
address _token
) public
{
require(_startTime >= now);
require(_endTime >= _startTime);
require(_rate > 0);
require(_wallet != address(0));
require(_token != 0x0);
startTime = _startTime;
endTime = _endTime;
rate = _rate;
wallet = _wallet;
token = Token(_token);
}
// fallback function don't accept purchase
function () external payable {
buyTokens(msg.sender);
}
/**************************************************************************
* Finalization methods
**************************************************************************/
/**
* @dev Must be called after crowdsale ends, to do some extra finalization
* work. Calls the contract's finalization function.
*/
function finalize() onlyOwner public {
require(!isFinalized);
require(hasEnded());
finalization();
Finalized();
isFinalized = true;
}
// Overrided methods
/**
* @dev Finalizes the crowdsale
*/
function finalization() internal {
// Mint tokens up to MAX_TOKENS_AVAILABLE and assign to owner wallet
if (token.totalSupply() = startTime) && (now = MAX_TOKENS_FOR_SALE;
return now > endTime || capReached;
}
}
but still no avail. In Mist, it still says the execute will fail...etherscan said the transaction is canceled, and failed...
https://rinkeby.etherscan.io/tx/0x306a9cfebf689342eec94e6e26d8fe9c7d8dad35538d36d128d477ff4d49e92b
the start / end time is within the valid period:
- start time: 1512981000 Is equivalent to: 12/11/2017 @ 8:30am (UTC)
- end time: 1513130400 Is equivalent to: 12/13/2017 @ 2:00am (UTC)
I just couldn't figure out why it would fail for such a simple contract, and not knowing where to start debugging is frustrating...
buy
orbuyTokens
functions? You can only send ether through functions withpayable
modifier, your fallback function is payable but it doesrevert()
immediately so you cannot senr ether directly, only withbuy
andbuyTokens
.buy()
. I do not use Mist/Metamask but I doubt they automaticaly callbuy()
from a contract, the most reasonable function to call is the fallback but you have disabled it. In any case you should check all the requires and asserts (including those in modifiers) called bybuy
orbuyTokens
.