I am learning solidity by transcribing code from "Practical Smart Contract Development with Solid and Etherium"(OREILLY).
To work around the integer overflow problem, I used SafeMath and got the following error in truffle test.
Contract: Fundraiser
setBeneficiary
making donations
making donations
increase the totalDonations amaount:
ReferenceError: newDonationsCount is not defined
at Context. (test/fundraiser_test.js:113:28)
Here is the code for test(test/fundraiser_test.js)
const FundraiserContract = artifacts.require("Fundraiser");
const truffleAssert = require('truffle-assertions');
contract("Fundraiser", accounts => {
let fundraiser;
const name = "Beneficiary Name";
const url = "beneficiaryname.org";
const imageURL = "https://placekitten.com/600/350";
const description = "Beneficiary description";
const beneficiary = accounts[1];
const owner = accounts[0];
beforeEach(async () => {
fundraiser = await FundraiserContract.new(
name,
url,
imageURL,
description,
beneficiary,
owner
)
});
describe("initialization", () => {
it("gets the beneficiary name", async () => {
const actual = await fundraiser.name();
assert.equal(actual, name, "names should match");
});
it("gets the beneficiary url", async () => {
const actual = await fundraiser.url();
assert.equal(actual, url, "url should match");
});
it("gets the beneficiary image url", async () => {
const actual = await fundraiser.imageURL();
assert.equal(actual, imageURL, "imageURL should match");
});
it("gets the beneficiary description", async () => {
const actual = await fundraiser.description();
assert.equal(actual, description, "description should match");
});
it("gets the beneficiary", async () => {
const actual = await fundraiser.beneficiary();
assert.equal(actual, beneficiary, "beneficiary addresses should match");
});
it("gets the owner", async () => {
const actual = await fundraiser.owner();
assert.equal(actual, owner, "bios should match");
});
});
describe("setBeneficiary", () => {
const newBeneficiary = accounts[2];
it("updated beneficiary when called by owner account", async () => {
await fundraiser.setBeneficiary(newBeneficiary, {from: owner});
const actualBeneficiary = await fundraiser.beneficiary();
assert.equal(actualBeneficiary, newBeneficiary, "beneficiaries should match");
});
it("throws and error when called from a non-owner account", async () => {
await truffleAssert.fails(
fundraiser.setBeneficiary(newBeneficiary, { from: accounts[3]}),
truffleAssert.ErrorType.REVERT,
"Ownable: caller is not the owner"
);
});
describe("making donations",()=>{
const value = web3.utils.toWei('0.0289');
const donor = accounts[2];
it("increases myDonationsCount", async () => {
const currentDonationsCount = await fundraiser.myDonationsCount(
{from: donor}
);
await fundraiser.donate({from: donor, value});
const newDonationsCount = await fundraiser.myDonationsCount({from: donor});
assert.equal(
1,
newDonationsCount - currentDonationsCount,
"myDonationsCount should increment by 1");
});
it("includes donation in myDonations", async () => {
await fundraiser.donate({from: donor, value});
const {values, dates} = await fundraiser.myDonations(
{from: donor}
);
assert.equal(
value,
values[0],
"values should match"
);
assert(dates[0], "date should be present");
});
describe("making donations", ()=>{
it("increase the totalDonations amaount", async()=>{
const currentTotalDonations = await fundraiser.totalDonations();
await fundraiser.donate({from: donor, value});
const newDonationsCount = await fundraiser.totalDonations();
const diff = newTotakDonations - currentTotalDonations;
assert.equal(
diff,
value,
"difference should match the donation value"
);
});
});
});
})
});
Here is the code for contruct
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
contract Fundraiser is Ownable {
using SafeMath for uint256;
uint256 public totalDonations;
struct Donation{
uint256 value;
uint256 date;
}
mapping(address=>Donation[])private _donations;
string public name;
string public url;
string public imageURL;
string public description;
address payable public beneficiary;
constructor(
string memory _name,
string memory _url,
string memory _imageURL,
string memory _description,
address payable _beneficiary,
address _custodian
)
public
{
name = _name;
url = _url;
imageURL = _imageURL;
description = _description;
beneficiary = _beneficiary;
transferOwnership(_custodian);
}
function setBeneficiary(address payable _beneficiary) public onlyOwner {
beneficiary = _beneficiary;
}
function myDonationsCount() public view returns(uint256){
return _donations[msg.sender].length;
}
function donate() public payable{
Donation memory donation = Donation({
value: msg.value,
date: block.timestamp
});
_donations[msg.sender].push(donation);
totalDonations = totalDonations.add(msg.value);
}
function myDonations() public view returns(
uint256[] memory values,
uint256[] memory dates
)
{
uint256 count = myDonationsCount();
values = new uint256[](count);
dates = new uint256[](count);
for (uint256 i = 0; i < count; i++) {
Donation storage donation = _donations[msg.sender][i];
values[i] = donation.value;
dates[i] = donation.date;
}
return (values, dates);
}
}
The entire code can be found here.
thnk you,