Skip to content

Commit

Permalink
Crowdfunding events
Browse files Browse the repository at this point in the history
  • Loading branch information
antico5 committed Oct 28, 2021
1 parent d2eb901 commit 48842d3
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 20 deletions.
13 changes: 13 additions & 0 deletions crowdfunding/contracts/CrowdFunding.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ contract CrowdFunding is Ownable {
}

event RequestCreated(uint indexed requestId, string description, address indexed recipient, uint value);
event Contributed(address indexed contributor, uint value);
event Voted(address indexed voter, uint indexed requestId);
event Executed(uint indexed requestId);
event Refunded(address indexed contributor, uint value);

modifier onFailed() {
require(block.timestamp > deadline && raisedAmount < goal);
Expand Down Expand Up @@ -63,6 +67,8 @@ contract CrowdFunding is Ownable {

_addContribution(msg.value);
raisedAmount += msg.value;

emit Contributed(msg.sender, msg.value);
}

function getRefund() public onlyContributors onFailed {
Expand All @@ -71,6 +77,8 @@ contract CrowdFunding is Ownable {
raisedAmount -= refundAmount;
contributorsCount--;
payable(msg.sender).transfer(refundAmount);

emit Refunded(msg.sender, refundAmount);
}

receive() external payable {
Expand Down Expand Up @@ -112,6 +120,8 @@ contract CrowdFunding is Ownable {

requests[requestId].voters[msg.sender] = true;
requests[requestId].votersCount++;

emit Voted(msg.sender, requestId);
}

function didVote(uint256 requestId, address contributor) public view returns (bool) {
Expand All @@ -123,6 +133,9 @@ contract CrowdFunding is Ownable {
require(request.votersCount >= contributorsCount/2, 'need more than half of contributors votes');
require(address(this).balance >= request.value, 'not enough funds');

request.executed = true;
payable(request.recipient).transfer(request.value);

emit Executed(requestId);
}
}
67 changes: 47 additions & 20 deletions crowdfunding/test/crowdfunding_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,21 @@ describe("CrowdFunding", function () {
expect(await contract.contributorsCount()).to.eq(2)
});

it("emits Contributed event", async () => {
await expect(contract.contribute({value: 1000})).to
.emit(contract, 'Contributed')
.withArgs(signer.address, 1000)
});

it("rejects if deadline is over", async () => {
const hrep = hre as any;
await hre.timeAndMine.increaseTime("601")
await hre.timeAndMine.increaseTime("602")

expect(contract.contribute({value: 100000})).to.revertedWith('already finished')
await expect(contract.contribute({value: 100000})).to.revertedWith('already finished')
});

it("rejects if the deposit amount is too low", async () => {
expect(contract.contribute({value: 99})).to.revertedWith('minimum contribution')
await expect(contract.contribute({value: 99})).to.revertedWith('minimum contribution')
});
});

Expand All @@ -63,7 +69,7 @@ describe("CrowdFunding", function () {
await contract.contribute({value: 500});

// Pass deadline
await hre.timeAndMine.increaseTime("601")
await hre.timeAndMine.increaseTime("602")

const oldBalance = await ethers.provider.getBalance(signer.address);

Expand All @@ -78,20 +84,32 @@ describe("CrowdFunding", function () {
expect(await contract.contributorsCount()).to.eq(0)
});

it("emits Refunded event", async () => {
await contract.contribute({value: 1000});
await contract.contribute({value: 500});

// Pass deadline
await hre.timeAndMine.increaseTime("602")

await expect(contract.getRefund()).to
.emit(contract, 'Refunded')
.withArgs(signer.address, 1500)
});

it("fails if the crowdfund didnt finish", async () => {
await contract.contribute({value: 1000});

// Dont pass deadline
await hre.timeAndMine.increaseTime("599")

expect(contract.getRefund()).to.revertedWith('')
await expect(contract.getRefund()).to.revertedWith('')
});

it("fails if the user is not a contributor", async () => {
// Pass deadline
await hre.timeAndMine.increaseTime("601")
await hre.timeAndMine.increaseTime("602")

expect(contract.getRefund()).to.revertedWith('')
await expect(contract.getRefund()).to.revertedWith('')
});
});

Expand All @@ -108,7 +126,7 @@ describe("CrowdFunding", function () {
});

it("can be created only by the owner", async () => {
expect(contract.connect(otherSigner).createRequest('Test request', signer.address, 1000)).to.revertedWith('owner')
await expect(contract.connect(otherSigner).createRequest('Test request', signer.address, 1000)).to.revertedWith('owner')
});
});

Expand All @@ -135,12 +153,12 @@ describe("CrowdFunding", function () {
});

it("only allows contributors to vote", async () => {
expect(contract.connect(otherSigner).vote(0)).to.revertedWith('only contributors')
await expect(contract.connect(otherSigner).vote(0)).to.revertedWith('only contributors')
});

it("doesnt allow you to vote twice", async () => {
expect(contract.vote(0)).to.not.be.reverted;
expect(contract.vote(0)).to.be.revertedWith('already voted')
await expect(contract.vote(0)).to.not.be.reverted;
await expect(contract.vote(0)).to.be.revertedWith('already voted')
});

it("doenst allow you to vote if request was already executed", async () => {
Expand All @@ -150,34 +168,39 @@ describe("CrowdFunding", function () {
}
})

expect(contract.vote(0)).to.revertedWith('already been executed')
await expect(contract.vote(0)).to.revertedWith('already been executed')
});
});

describe("when the campaign was not funded", function () {
it("doesnt allow you to vote", async () => {
await contract.contribute({value: 1000}); // user is contributor
expect(contract.vote(0)).to.be.revertedWith('didnt reach its goal')
await expect(contract.vote(0)).to.be.revertedWith('didnt reach its goal')
});
});

});

describe("makePayment", function () {
it("transfers eth to the request recipient", async () => {
let recipient: SignerWithAddress
const requestValue = ethers.utils.parseEther('1.5');
let requestId: BigNumber;

beforeEach(async () => {
// contribute until goal is reached
await contract.connect(signer).contribute({value: ethers.utils.parseEther('5')})
await contract.connect(otherSigner).contribute({value: ethers.utils.parseEther('5')})
await contract.connect(yetAnotherSigner).contribute({value: ethers.utils.parseEther('5')})

const recipient = (await ethers.getSigners())[3]
const recipientOldBalance = await ethers.provider.getBalance(recipient.address)

const requestValue = ethers.utils.parseEther('1.5');

recipient = (await ethers.getSigners())[3]
const tx = await contract.createRequest('Test request', recipient.address, requestValue) as TransactionResponse
const receipt = await tx.wait()

requestId = BigNumber.from(receipt.logs[0].topics[1]) // second value of first emmited event
});

const requestId = BigNumber.from(receipt.logs[0].topics[1]) // second value of first emmited event
it("transfers eth to the request recipient if there are enough votes", async () => {
const recipientOldBalance = await ethers.provider.getBalance(recipient.address)

await contract.connect(signer).vote(requestId)
await contract.connect(otherSigner).vote(requestId)
Expand All @@ -186,6 +209,10 @@ describe("CrowdFunding", function () {

const recipientNewBalance = await ethers.provider.getBalance(recipient.address)
expect(recipientNewBalance.sub(recipientOldBalance)).to.eq(requestValue)
const request = await contract.requests(requestId)
expect(request.executed).to.eq(true)

await expect(contract.makePayment(requestId)).to.be.revertedWith('already been executed')
});

it("is only callable by owner", async () => {
Expand Down

0 comments on commit 48842d3

Please sign in to comment.