Donations
Design a contract to receive donations from users, but remember a user can donate multiple times.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.13;
contract Donations {
mapping(address => uint256) public amountDonated;
receive() external payable {
// your code here
// amountDonated should store the amount
// the person donated
// don't forget a person can donate
// multiple times!
}
}
Problem Analysis
Variable amountDonated is a mapping store user’s donations. We need the donation amount can be accumulated since a same user can donate multiple times.
Coding
1
2
3
4
5
6
7
8
receive() external payable {
// your code here
// amountDonated should store the amount
// the person donated
// don't forget a person can donate
// multiple times!
amountDonated[msg.sender] += msg.value;
}
Test
1
2
3
4
5
6
7
8
9
10
11
➜ Donations git:(main) ✗ forge test -vvv
[⠊] Compiling...
[⠘] Compiling 19 files with Solc 0.8.25
[⠃] Solc 0.8.25 finished in 795.32ms
Compiler run successful!
Ran 1 test for test/Donations.t.sol:DonationsTest
[PASS] testDonate() (gas: 108731)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 877.58µs (90.75µs CPU time)
Ran 1 test suite in 179.55ms (877.58µs CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)
Go Deeper
Let’s go a little deeper.
Let see the test case. It only assign 1 ether to an address and assert the result to be 1 ether.
Let’s add case to test if the accumulated donation correct.
First we donate 1 eth, and then donate 2.5 eth, then we assert the total donation will be 3.5 eth.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function testAccumulate() external{
vm.deal(address(this), 5 ether);
(bool success, ) = address(donations).call{value: 1 ether}("");
require(success, "Send ether failed");
(success, ) = address(donations).call{value: 2.5 ether}("");
require(success, "Send ether failed");
assertEq(
donations.amountDonated(address(this)),
3.5 ether,
"expected amountDonated by address(this) to be 1 ether"
);
}
Test Again
1
2
3
4
5
6
7
8
9
10
11
12
➜ Donations git:(main) ✗ forge test -vvv
[⠊] Compiling...
[⠘] Compiling 19 files with Solc 0.8.25
[⠃] Solc 0.8.25 finished in 805.23ms
Compiler run successful!
Ran 2 tests for test/Donations.t.sol:DonationsTest
[PASS] testAccumulate() (gas: 46492)
[PASS] testDonate() (gas: 69435)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 4.72ms (1.08ms CPU time)
Ran 1 test suite in 194.03ms (4.72ms CPU time): 2 tests passed, 0 failed, 0 skipped (2 total tests)
Great, we add a new test case and passed the test!
Reference: Solidity Exercise - Donations