07 - AffiliateVaultV2¶
Affiliate-Provisionen via Merkle Proof
Übersicht¶
AffiliateVaultV2 verwaltet die Pull-basierten Affiliate-Provisionen. Affiliates werden während des Settlements berechtigt (Merkle Root) und können ihre Provisionen später selbst claimen - direkt oder über den ClaimRouter.
Datei: contracts/contracts/AffiliateVaultV2.sol
State Variables¶
mapping(uint256 => mapping(address => bool)) private _claimed; // Claim-Status
ISettlementV5Affiliate public settlement;
address public trustedClaimer; // Multicall3 Adresse
Merkle Roots im Settlement
Anders als PrizeVault speichert AffiliateVault keine eigenen Merkle Roots. Die Roots liegen in Settlement.affiliateMerkleRootByDay[dayId].
Merkle Leaf Struktur¶
bytes32 leaf = keccak256(abi.encode(
dayId, // uint256 - Tag der Provision
affiliate, // address - Affiliate-Wallet
amount // uint256 - Provisionsbetrag
));
Einfacher als der Prize-Leaf (keine Reassignment-Logik nötig).
claimAffiliate() - Hauptfunktion¶
function claimAffiliate(
uint256 dayId,
address affiliate,
address to,
uint256 amount,
bytes32[] calldata proof
) external nonReentrant
Ablauf¶
1. Access Control
2. Validierung
require(to == affiliate, "No redirection"); // Kein Fund-Redirect erlaubt
require(amount > 0, "Zero amount");
require(dayId > 0, "Invalid day");
3. Double-Claim Check
4. Merkle Root abrufen
5. Merkle Proof verifizieren
bytes32 leaf = keccak256(abi.encode(dayId, affiliate, amount));
require(MerkleProof.verifyCalldata(proof, root, leaf), "Invalid proof");
6. Payout via Settlement
settlement.payoutFromAffiliateVault(dayId, affiliate, to, amount);
// Settlement ruft ReserveVault.payPrize() auf
markClaimedFromSettlement()¶
- Nur Settlement kann Claims als ausgeführt markieren
- Setzt
_claimed[dayId][affiliate] = true - Wird nach erfolgreicher Auszahlung aufgerufen
Access Control¶
| Funktion | Owner (SAFE) | Settlement | TrustedClaimer | Affiliate |
|---|---|---|---|---|
| claimAffiliate | - | - | ✅ | ✅ (eigene) |
| markClaimedFromSettlement | - | ✅ | - | - |
| setSettlement | ✅ | - | - | - |
| setTrustedClaimer | ✅ | - | - | - |
Events¶
event AffiliateClaimed(uint256 dayId, address affiliate, uint256 amount);
event AffiliateClaimMarked(uint256 dayId, address affiliate);
Unterschiede zu PrizeVault¶
| Feature | PrizeVault | AffiliateVault |
|---|---|---|
| Merkle Root Storage | Lokal | In Settlement |
| Wallet Reassignment | Ja | Nein |
paidTo Redirect |
Ja (nach Reassignment) | Nein (to == affiliate erzwungen) |
| Double-Claim Tracking | In Settlement | Lokal (_claimed) |
Audit-Hinweise¶
Einfacherer Contract
AffiliateVault ist bewusst einfacher als PrizeVault gehalten. Affiliates sind bekannte Entities (keine Lost-Wallet-Problematik).
Pull-basiert
Affiliate-Payouts werden nicht während des Settlements ausgeführt. Der Betrag wird nur im Merkle Root committed. Der Affiliate muss aktiv claimen (Pull-Modell).