Sui.

Publication

Partagez vos connaissances.

Bekky.
Jul 17, 2025
Questions et Réponses avec des Experts

Meilleures pratiques pour la mise en œuvre de calendriers d'acquisition en Sui

Je suis en train de concevoir un système d'acquisition de jetons (par exemple, pour la répartition des équipes ou le blocage des investisseurs) dans Sui Move et je dois m'assurer que :

Sécurité — Pas de retraits prématurés

Flexibilité — Support pour les falaises, revêtement linéaire/progressif

Efficacité du gaz — Coûts de stockage minimaux

Transparence — Vérification facile du statut d'acquisition

Défis actuels :

  • Les blocages temporels de base fonctionnent mais manquent de contrôle granulaire
  • Difficultés liées à la gestion de plusieurs bénéficiaires
  • Je ne sais pas comment traiter les cas de licenciement anticipé

Des questions :

Quelle est l'architecture la plus sécurisée pour les contrats d'acquisition ?

Comment implémenter différentes courbes d'acquisition (linéaire, graduée, en falaise) ?

La meilleure façon de gérer les horaires révocables par rapport aux horaires irrévocables ?

Des vulnérabilités courantes à éviter ?

  • Sui
  • Move
0
1
Partager
Commentaires
.

Réponses

1
Evgeniy CRYPTOCOIN.
Jul 17 2025, 13:24

####1. Architecture d'acquisition de base

#####Mise en œuvre minimale viable

module vesting::linear {  
    use sui::coin;  
    use sui::clock;  
    use sui::balance;  
    use sui::tx_context;  

    struct VestingSchedule has key {  
        id: UID,  
        recipient: address,  
        total_amount: u64,  
        start_time: u64,  // Clock timestamp  
        duration_ms: u64, // Total vesting period  
        claimed: u64  
    }  

    /// Initialize vesting  
    public entry fn create(  
        recipient: address,  
        total_amount: u64,  
        duration_ms: u64,  
        clock: &Clock,  
        ctx: &mut TxContext  
    ) {  
        let schedule = VestingSchedule {  
            id: object::new(ctx),  
            recipient,  
            total_amount,  
            start_time: clock.timestamp_ms,  
            duration_ms,  
            claimed: 0  
        };  
        transfer::transfer(schedule, recipient);  
    }  
}  

Composantes clés :

  • Clockhorodatages basés sur des numéros de blocs (et non des numéros de blocs)
  • Objets de calendrier à gérer soi-même
  • Délivrance linéaire par défaut

####2. Modèles d'acquisition avancés

#####Falaise + Vestage linéaire

public fun claimable_amount(  
    schedule: &VestingSchedule,  
    clock: &Clock  
): u64 {  
    let elapsed = clock.timestamp_ms.saturating_sub(schedule.start_time);  

    // Cliff period (e.g., 1 year)  
    if (elapsed < CLIFF_MS) return 0;  

    // Linear vesting after cliff  
    let vested = (schedule.total_amount * elapsed) / schedule.duration_ms;  
    vested - schedule.claimed  
}  

#####Désignation graduelle (étapes multiples)

struct GradedVesting has key {  
    id: UID,  
    milestones: vector<Milestone>, // [{time: u64, percent: u8}]  
    claimed: u64  
}  

public fun graded_claimable(schedule: &GradedVesting, clock: &Clock): u64 {  
    let total_vested = 0;  
    let i = 0;  
    while (i < vector::length(&schedule.milestones)) {  
        let milestone = vector::borrow(&schedule.milestones, i);  
        if (clock.timestamp_ms >= milestone.time) {  
            total_vested = total_vested +  
                (schedule.total_amount * milestone.percent as u64) / 100;  
        };  
        i = i + 1;  
    };  
    total_vested - schedule.claimed  
}  

####3. Améliorations de sécurité

#####Attributions révocables (contrôles administratifs)

struct AdminCap has key { id: UID }  

public entry fn revoke(  
    schedule: VestingSchedule,  
    admin_cap: &AdminCap,  
    ctx: &mut TxContext  
) {  
    assert!(address_of(signer) == admin_cap.admin, EUnauthorized);  
    let remaining = schedule.total_amount - schedule.claimed;  
    coin::transfer(remaining, admin_cap.admin, ctx);  
    object::delete(schedule);  
}  

#####Anti-Fronrunning

public entry fn claim(  
    schedule: &mut VestingSchedule,  
    clock: &Clock,  
    ctx: &mut TxContext  
) {  
    let amount = claimable_amount(schedule, clock);  
    assert!(amount > 0, ENothingToClaim);  
    assert!(tx_context::epoch(ctx) == clock.epoch(), EStaleClock);  

    schedule.claimed = schedule.claimed + amount;  
    transfer::public_transfer(coin::mint(amount, ctx), schedule.recipient);  
}  

####4. Techniques d'optimisation du gaz

#####Calendriers d'acquisition par lots

struct BatchVesting has key {  
    id: UID,  
    schedules: Table<address, VestingSchedule>  
}  

// Claim all eligible in one TXN  
public entry fn batch_claim(batch: &mut BatchVesting, clock: &Clock) {  
    let iter = table::iter(&mut batch.schedules);  
    while (table::has_next(&iter)) {  
        let (addr, schedule) = table::next(&iter);  
        let amount = claimable_amount(schedule, clock);  
        if (amount > 0) transfer_coins(addr, amount);  
    }  
}  

#####Rabais sur l'entreposage

// Use small types where possible  
struct CompactVesting {  
    start_time: u64,  
    duration_ms: u32, // Sufficient for 49-day periods  
    claimed: u64  
}  

####5. Vulnérabilités courantes

Attaques chronométrées par Oracle

// UNSAFE: Trusting user-provided timestamps  
fun unsafe_claim(user_time: u64) { ... }  

Erreurs d'arrondi

// May leave "dust" unclaimed  
let vested = (amount * elapsed) / duration; // Use checked_math  

Logique de révocation manquante

// Irrevocable vesting may violate securities laws  
struct DangerousVesting { ... }  

####6. Stratégies de test

#####Test d'horloge simulée

#[test]  
fun test_cliff_period() {  
    let clock = mock_clock(0);  
    let schedule = create_vesting(CLIFF_MS * 2);  

    // Before cliff  
    test_clock::advance(&mut clock, CLIFF_MS - 1);  
    assert!(claimable(&schedule, &clock) == 0, ETestFail);  

    // After cliff  
    test_clock::advance(&mut clock, 1);  
    assert!(claimable(...) > 0, ETestFail);  
}  

#####Tests de fuzz

#[test]  
fun test_overflow_scenarios() {  
    let schedule = VestingSchedule {  
        start_time: u64::MAX - 1000,  
        duration_ms: 2000  
    };  
    // Should handle wrap-around correctly  
    claimable_amount(&schedule, &clock);  
}  
0
Commentaires
.

Connaissez-vous la réponse ?

Veuillez vous connecter et la partager.

Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.

431Publications636Réponses
Sui.X.Peera.

Gagne ta part de 1000 Sui

Gagne des points de réputation et obtiens des récompenses pour avoir aidé la communauté Sui à se développer.

Campagne de RécompensesJuillet