Hey @dan-i did you happen to get a chance to look at this? Sorry for the delay in follow up, I started to work on my 1st project and loss track of getting back to this assignment. Thanks again!
Do I understand this correctly? Typing await prior to a function call, tells the program to not proceed until the current function has finished executing?
Is it possible to add more than one option to a function call. For example, if I want to call the createPerson function in my test from accounts[2] and send it some ether from that account as well, is it valid to express that as shown below, or is only one option allowed?
await createPerson(Edward, 30, 190,{from: âaccounts[2]â}, value: 1000000000000000000);
Also, can anyone point me to the list of possible options. Iâve read through all the truffle documentation and it mentions: overwrite, gas, from, but Iâm certain more exist as Filip demonstrated the value option in this assignment.
Thanks @dan-i, dan you da man!
First I was getting zero balance for both, but after adding a createPerson function call into the test both ways now show a 1 ether balance and all test pass. Amen! Thank you brother!
Is it thus safe to assume that the tests are somehow run separately and do not know of what happened outside its own âitâ-clause?
Or why is the balance not increased by 1 ether when a createPerson with value 1 ether is called in a previous test section of the test-sequence?
Just curious to know better why things are going the way they are, always interested in the why, its important to get better. Thanks again!
Hi @Paul_Mun
Some considerations.
function createPerson(string memory name, uint age, uint height) public payable costs(1 ether)
This function uses a modifier called costs
and the min value is set to 1 ether.
You can therefore remove this require statement from createPerson() require(msg.value >= 1 ether);
Your struct Person has an id that is never used
struct Person {
uint id;
In function deletePerson
you assert assert(people[creator].age == 0);
This is not a good way to assert because the age can be set to 0 by the user.
When a new user is created (by calling createPerson()
) the only limitation to age is: require(age < 150, "Age needs to be below 150");
therefore 0 is a valid entry.
I can suggest to set the id in struct person (maybe starting from 1) so that you can assert the id == 0 when deleting a person.
Cheers,
Dani
Async functions are extremely important, I suggest you to take or Javascript course so that all these concepts will be clear.
Happy learning,
Dani
Hey @Kraken
Is it thus safe to assume that the tests are somehow run separately and do not know of what happened outside its own âitâ-clause?
This depends on how you write the tests.
In you case yes, they run individually.
Consider your code
it(âBalance should increase by 1 ether when a person is addedâ, async function (){
let instance = await People.deployed();
let balanceonchainBefore = web3.eth.getBalance(People.address);
await instance.createPerson(âBob Ahmedssonâ, 42, 180, {value: web3.utils.toWei(â1â, âetherâ)});
let balanceonchainAfter = web3.eth.getBalance(People.address);
assert(balanceonchainBefore + parseInt(web3.utils.toWei(â1â, âetherâ) == balanceonchainAfter), âBalance after adding a person should increas by 1 etherâ);
});
it(âowner should be able to withdraw contract balanceâ, async function (){
let instance = await People.deployed();
await truffleAssert.passes(instance.withdrawAll({from: accounts[0]}), truffleAssert.ErrorType.REVERT);
});
it(âactual contract balance should match with balance variableâ, async function (){
let instance = await People.deployed();
let balanceonchain = web3.eth.getBalance(People.address);
contractBalance = await instance.getBalance();
assert(balanceonchain == contractBalance, âBalance on blockchain and stored contract balance do not matchâ);
});
What you are doing here let instance = await People.deployed();
is creating a new instance of the contract in each test.
This is something I do not usually do.
I do suggest to deploy your contract once (in the before function()) and then use the same instance for all your tests.
Awesome, thank you so much! This helped me fix my problem!
Youâre my savior man!!!
thank u so much mate!
It works fine now when i use truffle develop!!
Thanks alot !
Of course no problem! I was stuck on that for a solid couple of hours so I figured Iâd help anyone out who was stuck on it too!
Thanks alot, I did search everywhere but couldnât find the solution, so you really saved med mate!
it(âverify contract balanceâ, async function() {
let balance = await web3.eth.getBalance(People.address);
console.log("contract balance "+ balance);
await ins.createPerson(âHK-add Balance1â, 35, 123, {value : web3.utils.toWei(â1â, âetherâ)});
let newBalance = await web3.eth.getBalance(People.address);
assert(parseInt(newBalance) > parseInt(balance), âNew balance should be higher to original balanceâ);
});
it(âOwner can withdrawAllâ, async function() {
let balance = await web3.eth.getBalance(People.address);
console.log("contract balance "+ balance);
await ins.createPerson(âHK-add Balance1â, 35, 123, {value : web3.utils.toWei(â1â, âetherâ)});
await ins.withdrawAll({from: accounts[0]});
let newBalance = await web3.eth.getBalance(People.address);
console.log("New balance "+ newBalance);
assert(parseInt(newBalance) === 0, âNew balance should be 0â);
});
Hi @dan-i , thanks again. I was thinking something along those lines, that let instance = await sounds like its awaiting for a new instance of the contract being deployed.
One of the videos had a section where you could get rid of duplicate code by using this before-method. So actually there is another benefit, everything does not get reset if yo do this way and there is only one instance of the contract running, which makes testing easier.
Thanks again. I will correct and proceed.
My Solution to deletePerson:
I use the flow of the test , since a person was already created in a prior test I simply test to delete that one first with the shouldnât delete then with the should delete
it("shouldn't delete a person without being owner", async function(){
let instance = await People.deployed();
await truffleAssert.fails(instance.deletePerson
(accounts[0],{from: accounts[1]}),truffleAssert.ErrorType.REVERT
);
});
it("Should delete a person when owner", async function() {
let instance = await People.deployed();
await truffleAssert.passes(instance.deletePerson
(accounts[0],{from: accounts[0]})
);
});
Value assignment: Since we use often the value of one eth to wei I have declared a variable at the top of the script that I just reuse:
var oneEth = web3.utils.toWei("1", "ether");
...
...
...
it("Should balance", async function () {
let instance = await People.new();
await instance.createPerson
("Bob", 65, 190, {from: accounts[1], value: oneEth});
let balance = await instance.balance();
let addressBalance = await web3.eth.getBalance(instance.address);
assert(balance == oneEth, "Balance should be 1 eth");
assert(balance == addressBalance,"Both balances should be equal" );
});
it("Should owner widhtdraw and balance", async function () {
let instance = await People.new();
let ownerBalance = await web3.eth.getBalance(accounts[0]);
await instance.createPerson
("Bob", 65, 190, {from: accounts[1], value: oneEth});
await truffleAssert.passes(instance.withdrawAll({from: accounts[0]}));
let newOwnerBalance = await web3.eth.getBalance(accounts[0]);
assert(newOwnerBalance > ownerBalance , "Owner balanche should be increased");
let addressBalance = await web3.eth.getBalance(instance.address);
assert(addressBalance == 0, "Contract balance should be 0");
});
it("Shouldn't non-owner widhtdraw", async function () {
let instance = await People.new();
await instance.createPerson
("Bob", 65, 190, {from: accounts[1], value: oneEth});
await truffleAssert.fails(instance.withdrawAll
({from: accounts[1]}),truffleAssert.ErrorType.REVERT);
let addressBalance = await web3.eth.getBalance(instance.address);
assert(addressBalance != 0, "Contract balance should not be 0");
});
function createPerson(string memory name, uint age, uint height) public payable costs(1 ether)
Whats the meaning of costs(1 ether) inside the function header?
it("should not allow deletePerson", async () => {
truffleAssert.fails(instance.deletePerson(accounts[0], { from: accounts[1] }));
});
it("should allow deletePerson", async () => {
truffleAssert.passes(instance.deletePerson(accounts[0], { from: accounts[0] }));
});
it("check Balance", async () => {
let tmpInstance = await People.new();
const oneEth = web3.utils.toWei("1", "ether");
await tmpInstance.createPerson("Julian", 70, 186, { value: oneEth, from: accounts[0] });
const contractBalance = await web3.eth.getBalance(tmpInstance.address);
assert(contractBalance === oneEth, "Balance does not match");
});
it("Ckeck Withdrawl with owner", async () => {
let tmpInstance = await People.new();
const oneEth = web3.utils.toWei("1", "ether");
// send value
await tmpInstance.createPerson("Julian", 70, 186, { value: oneEth, from: accounts[0] });
truffleAssert.passes(instance.withdrawlAll({ from: accounts[0] }));
});
it("Ckeck balance after Withdrawl with owner", async () => {
let tmpInstance = await People.new();
// send value
await tmpInstance.createPerson("Julian", 70, 186, { value: web3.utils.toWei("10", "ether"), from: accounts[1] });
const balanceBefore = (await web3.eth.getBalance(accounts[0]));
// withdrawl
await tmpInstance.withdrawlAll();
const balanceAfter = (await web3.eth.getBalance(accounts[0]));
assert(balanceBefore < balanceAfter, "Owner balance does not increased");
});
it("Ckeck balance after Withdrawl of contract", async () => {
let tmpInstance = await People.new();
const oneEth = web3.utils.toWei("1", "ether");
// send value
await tmpInstance.createPerson("Julian", 70, 186, { value: oneEth, from: accounts[0] });
// withdrawl
await tmpInstance.withdrawlAll();
const realBalance = await web3.eth.getBalance(tmpInstance.address);
const contractBalance = parseFloat(await tmpInstance.balance());
assert(contractBalance == 0, "Balance does not match in the Contract");
assert(contractBalance == realBalance, "Balance does not match Contract with Blockchain");
});```
Hi @niore
Thatâs a modifier.
Filip explains it perfectly here, check it out
https://academy.ivanontech.com/products/ethereum-smart-contract-programming-101-2/categories/4223200/posts/14181421
Think this should work
const People = artifacts.require("People");
const truffleAssert = require("truffle-assertions");
contract("People", async function(accounts){
it("shouldn't create a person with age over 150 years", async function(){
let instance = await People.deployed();
await truffleAssert.fails(instance.createPerson("Bob", 200, 190, {value: web3.utils.toWei("1", "ether")}), truffleAssert.ErrorType.REVERT);
});
it("shouldn't allow create a person without payment", async function(){
let instance = await People.deployed();
await truffleAssert.fails(instance.createPerson("John", 50, 190, {value: 1000}), truffleAssert.ErrorType.REVERT);
});
it("should set seniour status correctly", async function(){
let instance = await People.deployed();
await instance.createPerson("Paul", 65, 190, {value: web3.utils.toWei("1", "ether")});
let result = await instance.getPerson();
assert(result.senior === true, "Senior level not set");
});
it("shouldn't allow non-owner to delete person", async function(){
let instance = await People.deployed();
await instance.createPerson("Sue", 65, 190, {value: web3.utils.toWei("1", "ether"), from: accounts[0]});
await truffleAssert.fails(instance.deletePerson(accounts[0],{value:0, from: accounts[1]}), truffleAssert.ErrorType.REVERT);
});
it("should allow owner to delete person", async function(){
let instance = await People.deployed();
await instance.createPerson("Alice", 65, 190, {value: web3.utils.toWei("1", "ether"), from: accounts[1]});
await instance.deletePerson(accounts[1],{from: accounts[0]});
let result = await instance.getPerson({from: accounts[1]});
assert(result.name !== "Alice", "Person wasn't deleted");
});
it("shouldn't allow non-owner to withdrawAll", async function(){
let instance = await People.deployed();
await truffleAssert.fails(instance.withdrawAll({from: accounts[1]}), truffleAssert.ErrorType.REVERT);
});
it("should allow owner to withdrawAll", async function(){
let instance = await People.deployed();
await instance.createPerson("Alice", 65, 190, {value: web3.utils.toWei("1", "ether"), from: accounts[1]});
await instance.withdrawAll({from: accounts[0]});
let newbalance = await web3.eth.getBalance(instance.address);
assert(newbalance == 0, "Balance isn't zero after withdrawAll but is: " + newbalance);
});
});