Donor Tiers Vault
Donor Tiers Vault
The Scenario You're writing the contract layer for a charity platform. Anyone can send ETH along with a short message; the contract classifies each donor by their total contributed amount and lets the frontend query each donor's full history.
What You'll Build A single contract called DonorVault that records every donation as a struct, classifies donors into a tier enum based on cumulative amount, tracks the unique donor count, and exposes the view functions the frontend needs.
Requirements
- Tier Enum: The contract MUST define an enum
Tierwith these values, in this exact order:None,Bronze,Silver,Gold,Platinum. - Tier Boundaries: A donor's tier MUST be derived from their cumulative total in wei according to these strict boundaries:
- None: total = 0
- Bronze: 0 < total < 0.1 ether
- Silver: 0.1 ether ≤ total < 1 ether
- Gold: 1 ether ≤ total < 10 ether
- Platinum: 10 ether ≤ total (Test cases to check your math: 0 is None. 1 wei is Bronze. Exactly 0.1 ether is Silver. Exactly 10 ether is Platinum.)
- The Donation Struct: You MUST define a
Donationstruct containingamount,timestamp, andmessagein that exact order. - The Donate Function: The function
donate(string calldata message)MUST beexternal payable. - It MUST revert with a custom error
ZeroDonation()ifmsg.valueis 0. - It MUST record the
Donationin that donor's history. - It MUST update the donor's cumulative total correctly.
- Unique Donors: The contract MUST track the count of unique donors. Subsequent donations from the same address MUST NOT increment that count.
- Storage: Donor history MUST be stored exactly as
mapping(address => Donation[]). Do not use a flat array, and do not wrap the array inside another struct. - View Functions: The view functions
tierOf,donationCount,getDonation,uniqueDonorCount, andtotalDonatedByMUST behave as named and match the signatures shown in the starter code.
solidity
Loading...
Call
donate("First!")
value: 0.05 ETH • from: alice
donationCount(alice)
from: alice
expected: 1
totalDonatedBy(alice)
from: alice
expected: 50000000000000000
getDonation(alice, 0)
from: alice
expected: {"amount":"50000000000000000","timestamp":"0","message":"First!"}
donate("Second!")
value: 0.2 ETH • from: alice
donationCount(alice)
from: alice
expected: 2
totalDonatedBy(alice)
from: alice
expected: 250000000000000000
getDonation(alice, 1)
from: alice
expected: {"amount":"200000000000000000","timestamp":"0","message":"Second!"}