Passa al contenuto principale

Smart Contract

Savitri Network fornisce un runtime nativo per smart contract con standard token integrati, governance e supporto oracle.

Runtime dei Contract

I contract vengono eseguiti in un ambiente isolato (sandbox) con:

  • Misurazione del gas: Ogni operazione consuma gas per prevenire i loop infiniti
  • Slot di storage: Archiviazione chiave-valore tramite indirizzi di slot con hash Keccak256
  • Sistema di eventi: I contract emettono eventi per i consumatori esterni
  • Monitoraggio della memoria: I limiti di memoria del runtime prevengono attacchi DoS
  • Supporto all'aggiornamento: I contract possono essere aggiornati tramite governance

Standard Token

StandardTipoEquivalenteDescrizione
SAVITRI-20FungibileERC-20Trasferimenti token, approvazioni, indennità
SAVITRI-721Non Fungibile (NFT)ERC-721Proprietà token unici, trasferimenti, metadati
SAVITRI-1155Multi-AssetERC-1155Operazioni batch, fungibile/non fungibile misto

Contract Integrati

Governance

Sistema di proposta e votazione on-chain:

  • Crea proposte con titolo, descrizione e periodo di votazione
  • Vota a favore/contro
  • Esegui le proposte approvate
  • Specializzazione delle proposte FL (Federated Learning)

Vedi Governance per i dettagli.

Oracle

Sistema di feed di dati esterni:

  • Registra i provider oracle
  • Richiedi e invia dati
  • Verifica delle prove
  • Validazione dello schema

Vedi Sistema Oracle per i dettagli.

Interazione con i Contract tramite SDK

Utilizzo di ContractClient

use savitri_sdk::{ContractClient, Wallet, RpcClient};

let wallet = Wallet::from_private_key_hex("your_key")?;
let contract = ContractClient::from_url_and_wallet("http://localhost:8545", wallet)?;

// Chiama una funzione del contract
let tx_hash = contract.call_contract(
&"contract_address".to_string(),
b"transfer",
&encoded_args,
Some(0),
).await?;

Utilizzo di TransactionBuilder

use savitri_sdk::TransactionBuilder;

let tx = TransactionBuilder::new()
.to("contract_address")
.data(call_data) // function selector + encoded args
.value(0)
.nonce(nonce)
.fee(5_000_000_000_000_000) // 0.005 SAVT contract fee
.build_and_sign(&wallet)?;

Modello di Storage

I contract utilizzano un modello di storage basato su slot simile a Ethereum:

  • Slot 0-99: Riservati a BaseContract (proprietario, metadati)
  • Slot 100+: Storage specifico del contract

Gli indirizzi degli slot vengono derivati tramite hash Keccak256 per prevenire collisioni:

balance_slot = keccak256(address || SLOT_BALANCES_BASE)
allowance_slot = keccak256(spender || keccak256(owner || SLOT_ALLOWANCES_BASE))

Tutti i valori sono memorizzati come array di 32 byte (little-endian per i tipi numerici).

Costi del Gas

OperazioneCosto GasCommissione (SAVT)
Deploy contractVariabile0.005 base
Chiamata contractVariabile0.005 base
Scrittura storage (SSTORE)20.000Inclusa nel base
Lettura storage (SLOAD)200Inclusa nel base
Trasferimento token~50.0000.005
Mint NFT~80.0000.005
Voto governance~30.0000.005

Deploy dei Contract

I contract vengono distribuiti tramite transazioni speciali con to = None e il bytecode del contract nel campo data:

let deploy_tx = TransactionBuilder::new()
// Nessun .to() -- indica il deploy del contract
.data(contract_bytecode)
.value(0)
.nonce(nonce)
.fee(5_000_000_000_000_000)
.build_and_sign(&wallet)?;