I create a smart contract to sell my token.I am following the Dapp University(youtube channel) course.
I have done unit testing of smart contract.All test cases pass.
And I am trying to buy token on my client side application.So there is transaction failed.And this error comes VM Exception while processing transaction: revert:
Then I test buyTokens() function in truffle console.So,The same error comes.
Here is my solidity code:-
pragma solidity ^0.4.2;
import "./DappToken.sol";
contract DappTokenSale {
address admin;
DappToken public tokenContract;
uint256 public tokenPrice;
uint256 public tokensSold;
event Sell(address _buyer, uint256 _amount);
function DappTokenSale(DappToken _tokenContract, uint256 _tokenPrice) public {
admin = msg.sender;
tokenContract = _tokenContract;
tokenPrice = _tokenPrice;
}
function multiply(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x);
}
function buyTokens(uint256 _numberOfTokens) public payable {
require(msg.value == multiply(_numberOfTokens, tokenPrice));
require(tokenContract.balanceOf(this) >= _numberOfTokens);
require(tokenContract.transfer(msg.sender, _numberOfTokens));
tokensSold += _numberOfTokens;
Sell(msg.sender, _numberOfTokens);
}
// Ending Token DappTokenSale
function endSale() public {
// Require admin
require (msg.sender == admin);
// Transfer remaing DappToken to admin
require(tokenContract.transfer(admin,tokenContract.balanceOf(this)));
// Destroy Contract
selfdestruct(admin);
}
}
Here is my "DappToken" solidity code:-
pragma solidity ^0.4.2;
/**
* The contractName contract does this and that...
*/
contract DappToken {
// Name
string public name = "DappToken";
// Symbol
string public symbol = 'DAPP';
//standard
string public standard = 'DApp Token v1.0';
uint256 public totalSupply;
event Transfer(
address indexed _form,
address indexed _to,
uint256 _value
);
event Approval(
address indexed _owner,
address indexed _spender,
uint256 _value
);
mapping(address => uint256) public balanceOf;
mapping(address => mapping (address => uint256)) public allowance;
function DappToken (uint256 _intialSupply) public {
balanceOf[msg.sender] = _intialSupply;
totalSupply = _intialSupply;
//allcate the intial supply
}
//Transfar
function transfer(address _to,uint256 _value) public returns (bool success){
// Exception if account does not enough
require (balanceOf[msg.sender] >= _value);
// Transfar the balance
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
// Transfar Event
Transfer(msg.sender,_to,_value);
// Return a boolean
return true;
}
// approve
function approve(address _spender,uint256 _value) public returns (bool success){
//allowence
allowance[msg.sender][_spender] = _value;
// Approve event
Approval(msg.sender,_spender,_value);
return true;
}
// transfer form
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(_value <= balanceOf[_from]);
require(_value <= allowance[_from][msg.sender]);
// change the balance
balanceOf[_from] -= _value;
//update the balance
balanceOf[_to] += _value;
allowance[_from][msg.sender] -= _value;
emit Transfer(_from,_to,_value);
return true;
}
}
Here is my "test.js" code:-
var DappToken = artifacts.require('./DappToken.sol');
var DappTokenSale = artifacts.require('./DappTokenSale.sol');
contract('DappTokenSale', function(accounts) {
var tokenInstance;
var tokenSaleInstance;
var admin = accounts[0];
var buyer = accounts[1];
var tokenPrice = 1000000000000000; // in wei
var tokensAvailable = 750000;
var numberOfTokens;
it('initializes the contract with the correct values', function() {
return DappTokenSale.deployed().then(function(instance) {
tokenSaleInstance = instance;
return tokenSaleInstance.address
}).then(function(address) {
assert.notEqual(address, 0x0, 'has contract address');
return tokenSaleInstance.tokenContract();
}).then(function(address) {
assert.notEqual(address, 0x0, 'has token contract address');
return tokenSaleInstance.tokenPrice();
}).then(function(price) {
assert.equal(price, tokenPrice, 'token price is correct');
});
});
it('facilitates token buying', function() {
return DappToken.deployed().then(function(instance) {
// Grab token instance first
tokenInstance = instance;
return DappTokenSale.deployed();
}).then(function(instance) {
// Then grab token sale instance
tokenSaleInstance = instance;
// Provision 75% of all tokens to the token sale
return tokenInstance.transfer(tokenSaleInstance.address, tokensAvailable, { from: admin })
}).then(function(receipt) {
numberOfTokens = 10;
return tokenSaleInstance.buyTokens(numberOfTokens, { from: buyer, value: numberOfTokens * tokenPrice })
}).then(function(receipt) {
assert.equal(receipt.logs.length, 1, 'triggers one event');
assert.equal(receipt.logs[0].event, 'Sell', 'should be the "Sell" event');
assert.equal(receipt.logs[0].args._buyer, buyer, 'logs the account that purchased the tokens');
assert.equal(receipt.logs[0].args._amount, numberOfTokens, 'logs the number of tokens purchased');
return tokenSaleInstance.tokensSold();
}).then(function(amount) {
assert.equal(amount.toNumber(), numberOfTokens, 'increments the number of tokens sold');
return tokenInstance.balanceOf(buyer);
}).then(function(balance) {
assert.equal(balance.toNumber(), numberOfTokens);
return tokenInstance.balanceOf(tokenSaleInstance.address);
}).then(function(balance) {
assert.equal(balance.toNumber(), tokensAvailable - numberOfTokens);
// Try to buy tokens different from the ether value
return tokenSaleInstance.buyTokens(numberOfTokens, { from: buyer, value: 1 });
}).then(assert.fail).catch(function(error) {
assert(error.message.indexOf('revert') >= 0, 'msg.value must equal number of tokens in wei');
return tokenSaleInstance.buyTokens(800000, { from: buyer, value: numberOfTokens * tokenPrice })
}).then(assert.fail).catch(function(error) {
assert(error.message.indexOf('revert') >= 0, 'cannot purchase more tokens than available');
});
});
it('ends token sale', function() {
return DappToken.deployed().then(function(instance) {
// Grab token instance first
tokenInstance = instance;
return DappTokenSale.deployed();
}).then(function(instance) {
// Then grab token sale instance
tokenSaleInstance = instance;
// Try to end sale from account other than the admin
return tokenSaleInstance.endSale({ from: buyer });
}).then(assert.fail).catch(function(error) {
assert(error.message.indexOf('revert' >= 0, 'must be admin to end sale'));
// End sale as admin
return tokenSaleInstance.endSale({ from: admin });
}).then(function(receipt) {
return tokenInstance.balanceOf(admin);
}).then(function(balance) {
assert.equal(balance.toNumber(), 999990, 'returns all unsold dapp tokens to admin');
// Check that token price was reset when selfDestruct was called
// return tokenSaleInstance.tokenPrice();
// }).then(function(price) {
// assert.equal(price.toNumber(), 0, 'token price was reset');
});
});
});
I am new in this field.What is this error mean and why this error comes??Any one tell me What I mistake in code??.
Best Answer
it could be a token provision issue: dappTokenSale contract address doesn't have any DAPP token being provisioned yet, which results to this following line of code failed in DappTokenSale.sol file
truffle console
to check if this is the case:truffle console
in the terminalDappToken.deployed().then(function(instance) { return instance.balanceOf(tokenSaleAddress) })
wheretokenSaleAddress
is displayed when you runtruffle migrate --reset
DappToken.deployed().then(function(instance) { instance.transfer(tokenSaleAddress, 750000, { from:admin }) })
, where admin is the 1st account in Ganche, assuming you are going to provision 750000 out of 1000000 to the tokenSaleAddress