-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Description
Tour d’horizon complet du contrat
(je laisse de côté la commission ; on considère que tu as appliqué le correctif proposé.)
| Section | Points bloquants / pièges | Pourquoi c’est gênant | Correctif suggéré |
|---|---|---|---|
| deposit | Paramètre last_id passé par l’utilisateur | Un caller malveillant peut transmettre un last_id erroné ⇒ assert(pos_id == current+1) -> fail et DoS sur le contrat. | Supprime ce paramètre : calcule pos_id directement à partir de next_id. |
| total_collateral stocke une valeur USD | Au dépôt on additionne price × amount, mais au retrait et à la liquidation on soustrait la valeur au cours du jour ; la somme mélange donc plusieurs cours. | Soit :• stocke la quantité de crédits,• soit mets à jour périodiquement la valeur via un oracle externe. | |
| mint | Aucune limite de dette ! (pas d’assert) | Un emprunteur peut frapper infiniment de l’USDA, rendant la sûreté du système nulle. | Ajoute assert(new_debt ≤ max_debt); juste avant l’écriture de metas. |
| fut_mint.await() avant les checks ? | Tu fais correctement les asserts avant le await: parfait. | ||
| burn | OK côté logique, mais surveille les conversions u128 ↔ u64 si tu autorises de gros montants. | ||
| withdraw | • Nous avons déjà corrigé la logique fees/netto.• Rounding : pour amount < 100 le fee peut tomber à 0. | Ajoute un require(amount ≥ 100) ou calcule sur u128 puis as u64 avec un contrôle. | |
| liquidate | Condition de liquidation erronée (unités)price <= meta.price_liq compare :• price = USDA/credit• price_liq = USDA totales (coll_val × LLTV). | La condition sera (presque) toujours vraie ! Un opérateur peut liquider des positions saines. | Calcule le LTV :let coll_val_current = meta.coll_amt * price;assert(meta.debt_amt * 100u128 >= coll_val_current * LLTV); |
| Paramètre inutile debt_amt | Pas utilisé → confusion. | Supprime-le. | |
| total_collateral mis à jour avec un nouveau prix dans claim_collateral | Même problème d’incohérence de valeur évoqué plus haut. | Si tu stockes la quantité, soustrais simplement amount. | |
| claim_refund / claim_collateral | Pas de protection contre un double appel entre refund et collateral ? | Non critique mais tu peux ajouter un liquidated_ids check ou events distincts. | |
| claim_fees | • Unités mixées (credits vs USD).• amount en u64 : risque d’overflow si la banque grossit. | Voir section fees précédemment. | - Stocke les frais dans la même unité que tu transfères.- Utilise u128 partout ou élimine le paramètre amount : le contrat calcule et envoie tout. |
| Overflow / precision | Multiplications u128 * u128 (par ex. coll_amt * price) peuvent dépasser 2¹²⁸-1 si tu autorises > 10²⁰ tokens. | Les VM Aleo tronquent silencieusement. | Place des garde-fous :assert(coll_amt <= MAX_COLL) ou calcule sur u256 si dispo. |
| Gas / DoS | Les mappings ne sont jamais purgés pour les positions closes hors liquidation. | Le stockage grossit indéfiniment. | Ajoute metas.remove(id) dans une transition close_position (après remboursement intégral) pour libérer l’état. |
| UX / Front-end | initialize enregistre un token déjà connu à chaque déploiement : protégé par is_owner, mais assure-toi que l’ID unique n’est pas déjà pris sur mainnet. | – | – |
Schéma de correctif (extraits)
// ------------- deposit -------------
async transition deposit(
public amount: u64,
public price: u128,
private caller: address,
private token_record: credits.aleo/credits
) -> (Position, credits.aleo/credits, Future) {
let pos_id: u64 = next_id.get_or_use(USDA_TOKEN_ID, 0u64) + 1u64;
let (token, fut) = credits.aleo/transfer_private_to_public(token_record, CONTRACT, amount);
return (Position{ owner: caller, id: pos_id },
token,
finalize_deposit(fut, pos_id, amount, price));
}
// ------------- mint (ajout du check) -------------
assert(new_debt <= max_debt); // interdit le sur-endettement
// ------------- liquidation -------------
let coll_val_current: u128 = meta.coll_amt * price;
let over_leveraged: bool = meta.debt_amt * 100u128 >= coll_val_current * LLTV;
assert(over_leveraged);
// ------------- withdraw -------------
let fee_amount: u128 = (amount as u128 * FEES as u128) / 100u128;
let net_amount: u64 = (amount as u128 - fee_amount) as u64;
let (token, fut) = credits.aleo/transfer_public_to_private(self.caller, net_amount);
total_fees += fee_amount; // même unité que tu transféreras au Treasury
TL;DR – les quatre « bugs rouges »
-
Aucune limite sur
mint→ inflation infinie. -
Condition de liquidation compare des grandeurs incompatibles.
-
withdrawrenvoie la commission au lieu du montant net. -
Incohérence d’unités entre
total_feeset le transfert réel.
Corrige ces points, choisis une unité (credits ou USD) pour toutes les agrégations, et retire le paramètre last_id. Le reste est plutôt bien structuré !
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels