When I run truffle test
on terminal I get the following error Error: Attempting to run transaction which calls a contract function, but recipient address 0x3ad2c00512808bd7fafa6dce844a583621f3df87 is not a contract address
I don't understand why I get this because my build
folder is normal meaning if I run truffle migrate --reset
the address in the terminal is the same as the address in the build file. when I run truffle migrate it works. Also, every time I run the truffle test the recipient address always changes. I don't know what do to please help.
One other thing this only happens once I use the code selfdestruct(admin);
then I get this error. the admin is = to msg.sender which is the first account in the ganache so I don't know what's wrong.
I am using this video. I have done all the other videos of this guy and everything is fine until now at minute 15:11 he does the final test and for him, it works but for me, it gives me the error above.
Anyone, please help
These is my test (javascript)
var CinoCoin = artifacts.require("./CinoCoin.sol");
var CinoCoinSale = artifacts.require("./CinoCoinSale.sol");
contract('CinoCoinSale', function(accounts) {
var tokenInstance;
var tokenSaleInstance;
var admin = accounts[0];
var buyer = accounts[1];
var tokenPrice = 1000000000000000; // in wei 0.01 ether
var tokensAvailable = 750000;
var numberOfTokens;
it('initializes the contract with the correct values', function() {
return CinoCoinSale.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('facilitats token buying', function() {
return CinoCoin.deployed().then(function(instance) {
//Grab token instance first
tokenInstance = instance;
return CinoCoinSale.deployed();
}).then(function(instance) {
//Then grab token sale instance
tokenSaleInstance = instance;
//Provision 75% of all tokens to the token sale contract
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, 'connot purchase more tokens than available');
});
});
it('ends token sale', function () {
return CinoCoin.deployed().then(function(instance) {
//Grab token instance first
tokenInstance = instance;
return CinoCoinSale.deployed();
}).then(function(instance) {
//Then grab token sale instance
tokenSaleInstance = instance;
//try to end sale from account other than 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 cino coins to admin');
//Check that the token price was reset when selfFestruct was called
return tokenSaleInstance.tokenPrice();
}).then(function(price) {
assert.equal(price.toNumber(), 0, 'token price was reset');
});
});
});
And this is my contract code (solidity)
pragma solidity ^0.4.23;
import "./CinoCoin.sol";
contract CinoCoinSale {
address admin;
CinoCoin public tokenContract;
uint256 public tokenPrice;
uint256 public tokensSold;
event Sell(address _buyer, uint256 _amount);
function CinoCoinSale(CinoCoin _tokenContract, uint256 _tokenPrice) public {
//Assign an admin / an external account connected to the blockchain that has certain priviliges
admin = msg.sender;
//Assign token contract
tokenContract = _tokenContract;
//Token Price how much the token will cost
tokenPrice = _tokenPrice;
}
//multiply function for
function multiply(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x);
}
//Buy tokens
function buyTokens(uint256 _numberOfTokens) public payable {
//Require that the value is equal to tokens
require(msg.value == multiply(_numberOfTokens, tokenPrice));
//Require that there are enough tokens in the contrat
require(tokenContract.balanceOf(this) >= _numberOfTokens);
//Require the transfer is successful
require(tokenContract.transfer(msg.sender, _numberOfTokens));
//Keep track of number of tokens sold
tokensSold += _numberOfTokens;
//Trigger a sell event
Sell(msg.sender, _numberOfTokens);
}
//ending token CinoCoinSale
function endSale()public {
//Only an admin can end the end the sale
require(msg.sender == admin);
//Transfer the amount of token in the sale back to the admin
require(tokenContract.transfer(admin, tokenContract.balanceOf(this)));
//Destroy contract
selfdestruct(admin);
}
}
It says my test are passing when I comment out the selfdestruct(admin);
so it seems to be a probelm with that
thanks for the help
glad you fixed the error already. While looking at your code I noticed that the test file is quite difficult to follow because of the large promise chains. I converted the file to async/await, which might be easier to maintain and debug in the future.
I also noticed that you are trying to assert emitted events and reverts by manually checking the logs, and catching the revert exception. I actually wrote a library to make this a bit easier, so I added the code for this as well.
The library can be installed with npm:
npm install truffle-assertions
After this, the new test code should work. I hope this helps, and good luck with your Dapp development.
const CinoCoin = artifacts.require("CinoCoin");
const CinoCoinSale = artifacts.require("CinoCoinSale");
const truffleAssert = require("truffle-assertions");
contract('CinoCoinSale', function(accounts) {
let tokenInstance;
let tokenSaleInstance;
let admin = accounts[0];
let buyer = accounts[1];
let tokenPrice = 1000000000000000; // in wei 0.01 ether
let tokensAvailable = 750000;
it('initializes the contract with the correct values', async function() {
tokenInstance = await CinoCoin.deployed();
tokenSaleInstance = await CinoCoinSale.deployed();
assert.notEqual(tokenSaleInstance.address, 0x0, 'has contract address');
assert.notEqual(await tokenSaleInstance.tokenContract(), 0x0, 'has token contract address');
assert.equal(await tokenSaleInstance.tokenPrice(), tokenPrice, 'token price is correct');
assert.equal(await tokenSaleInstance.admin(), admin, 'admin is correct');
});
it('facilitates token buying', async function() {
tokenInstance = await CinoCoin.deployed();
tokenSaleInstance = await CinoCoinSale.deployed();
await tokenInstance.transfer(tokenSaleInstance.address, tokensAvailable, { from: admin });
const numberOfTokens = 10;
const receipt = await tokenSaleInstance.buyTokens(numberOfTokens, { from: buyer, value: numberOfTokens * tokenPrice });
truffleAssert.eventEmitted(receipt, 'Sell', (ev) => {
return ev._buyer === buyer && ev._amount.toNumber() === numberOfTokens;
});
const tokensSold = await tokenSaleInstance.tokensSold();
assert.equal(tokensSold.toNumber(), numberOfTokens, 'increments the number of tokens sold');
const buyerBalance = await tokenInstance.balanceOf(tokenSaleInstance.address);
assert.equal(buyerBalance.toNumber(), numberOfTokens);
const tokenSaleBalance = await tokenInstance.balanceOf(tokenSaleInstance.address);
assert.equal(tokenSaleBalance.toNumber(), tokensAvailable - numberOfTokens);
truffleAssert.reverts(
tokenSaleInstance.buyTokens(numberOfTokens, { from: buyer, value: 1 }),
null,
'msg.value must equal number of tokens in wei'
);
truffleAssert.reverts(
tokenSaleInstance.buyTokens(800000, { from: buyer, value: numberOfTokens * tokenPrice }),
null,
'connot purchase more tokens than available'
);
});
it('ends token sale', async function () {
tokenInstance = await CinoCoin.deployed();
tokenSaleInstance = await CinoCoinSale.deployed();
truffleAssert.reverts(tokenSaleInstance.endSale({ from: buyer }), null, 'must be admin to end sale');
await tokenSaleInstance.endSale({ from: admin });
const adminBalance = await tokenInstance.balanceOf(admin);
assert.equal(adminBalance.toNumber(), 999990, 'returns all unsold cino coins to admin');
const tokenPrice = await tokenSaleInstance.tokenPrice();
assert.equal(tokenPrice.toNumber(), 0, 'token price was reset');
});
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.