User Story:
As a donor, I want to send tokens to the campaign contract so that my donation is recorded transparently on-chain.
Acceptance Criteria:
fn donate(env: Env, donor: Address, amount: i128, asset: AssetInfo)
donor.require_auth() called
- Validates: amount > 0, asset is accepted, campaign is active, deadline not passed
- Transfers tokens from donor to contract using Soroban token interface
- Updates
raised_amount and DonorRecord
- Emits
donation_received event with donor, amount, asset
User Story:
As a donor, I want to send tokens to the campaign contract so that my donation is recorded transparently on-chain.
Acceptance Criteria:
fn donate(env: Env, donor: Address, amount: i128, asset: AssetInfo)donor.require_auth()calledraised_amountandDonorRecorddonation_receivedevent with donor, amount, asset