Environnement d'Exécution des Contrats
L'environnement d'exécution des contrats Savitri exécute les contrats intelligents dans un environnement isolé avec comptage de gaz, isolation du stockage et émission d'événements.
Flux d'Exécution
Contract Call TX arrives
│
▼
BaseContract validation
│ check paused, owner, reserved slots
▼
Gas Meter initialization
│ gas_limit from TX fee
▼
ContractStorage setup
│ load contract state, init cache
▼
Function dispatch
│ match function_selector → handler
▼
Execution (with gas tracking)
│ SLOAD, SSTORE, events, calls
▼
Result
├── Success → commit storage, emit events
└── Failure → revert all changes
BaseContract
Tous les contrats étendent BaseContract. Les emplacements 0 à 99 sont réservés :
| Emplacement | Champ | Taille | Description |
|---|---|---|---|
| 0 | owner | 32 octets | Adresse du propriétaire du contrat |
| 1 | version | u64 | Version du contrat |
| 2 | governance_hook | bool | Intégration de gouvernance activée |
| 3 | fee_hook | bool | Logique de frais personnalisée activée |
| 4 | paused | bool | État de pause du contrat |
| 5-99 | Réservé | - | Usage futur |
Fonctions de BaseContract
| Fonction | Accès | Description |
|---|---|---|
owner() | Public | Obtenir le propriétaire du contrat |
transfer_ownership(new_owner) | Propriétaire uniquement | Transférer la propriété |
version() | Public | Obtenir la version du contrat |
upgrade(new_version) | Propriétaire uniquement | Mettre à niveau le contrat |
pause() | Propriétaire uniquement | Mettre en pause toutes les opérations |
unpause() | Propriétaire uniquement | Reprendre les opérations |
Comptage de Gaz
Coûts en Gaz
| Opération | Gaz | Description |
|---|---|---|
SLOAD | 100 | Lecture du stockage |
SSTORE (nouveau) | 20 000 | Écriture du stockage (emplacement vide) |
SSTORE (mise à jour) | 5 000 | Écriture du stockage (emplacement existant) |
CALL | 2 300 | Appel entre contrats |
CREATE | 32 000 | Déploiement de contrat |
TRANSFER | 300 | Transfert de jeton |
LOG | 375 | Émission d'événement (base) |
LOG_TOPIC | 375 | Par sujet supplémentaire |
LOG_DATA | 8 | Par octet de données d'événement |
CALLDATA | 16 | Par octet de données d'appel |
Comptabilité par Lots
Le compteur de gaz utilise une comptabilité par lots (100 opérations par lot) pour réduire la surcharge. Le gaz est validé par lots plutôt que par opération.
Limite de Gaz
La limite de gaz est dérivée des frais de transaction :
gas_limit = tx.fee / gas_price
Si le gaz est épuisé pendant l'exécution, la transaction entière est annulée.
Stockage des Contrats
Modèle Basé sur les Emplacements
Chaque contrat dispose d'un magasin clé-valeur indépendant où les clés sont des numéros d'emplacement u64 et les valeurs sont des tableaux de 32 octets.
Dérivation des Emplacements
Pour les mappages, les emplacements sont dérivés en utilisant Keccak256 pour éviter les collisions :
// Simple value
slot = FIXED_SLOT_NUMBER
// Mapping (address → value)
slot = keccak256(address || base_slot)[0..8] as u64
// Nested mapping (address → address → value)
inner = keccak256(outer_key || base_slot)
slot = keccak256(inner_key || inner)[0..8] as u64
Arbre de Merkle
Le stockage des contrats maintient un arbre de Merkle pour la génération de preuves d'état.
Système d'Événements
Les contrats émettent des événements pour les consommateurs externes :
pub struct CustomEvent {
pub event_type: String, // e.g., "Transfer", "Approval"
pub topics: Vec<Vec<u8>>, // indexed fields
pub data: Vec<u8>, // non-indexed data
}
Événements standards (provenant de BaseContract) :
OwnershipTransferred(old_owner, new_owner)ContractUpgraded(old_version, new_version)Paused(by)Unpaused(by)
Déploiement de Contrat
1. Create DeployTransaction (to = None, data = bytecode)
2. Assign contract address (derived from deployer + nonce)
3. Initialize BaseContract (set owner, version)
4. Run contract constructor (initialize function)
5. Store ContractInfo in CF_CONTRACTS
6. Emit ContractDeployed event
Appels de Contrat
1. Parse function_selector from TX data
2. Load contract from CF_CONTRACTS
3. Check BaseContract state (not paused, etc.)
4. Initialize GasMeter with gas_limit
5. Execute function with ContractStorage
6. If success: commit storage changes, deduct gas
7. If failure: revert all changes
Interpréteur EVM
Le module evm_interpreter fournit une exécution basique du bytecode EVM pour la compatibilité avec les contrats Ethereum. Cela permet de déployer des contrats compilés en Solidity sur Savitri.
Surveillance Mémoire
Le memory_monitor suit l'utilisation de la mémoire en cours d'exécution pour prévenir les attaques par déni de service :
- Limites mémoire par contrat
- Suivi des allocations
- Terminaison automatique si les limites sont dépassées
Exécution Parallèle
Le module parallel permet l'exécution parallèle des contrats pour les transactions indépendantes :
- Analyse des dépendances entre transactions
- Détection des conflits sur les emplacements de stockage
- Exécution parallèle des transactions non conflictuelles
- Repli en série pour les transactions conflictuelles
Traçage des Contrats
Le module tracing fournit des traces d'exécution pour le débogage :
- Journal d'exécution pas à pas
- Suivi des lectures/écritures du stockage
- Consommation de gaz par opération
- Journal d'émission d'événements