DEV Community

Cover image for #2 - Introduction au développement de smartcontracts sur la blockchain Partisia
Kernel 🏴‍☠️
Kernel 🏴‍☠️

Posted on

#2 - Introduction au développement de smartcontracts sur la blockchain Partisia

Dans cette série d’articles je découvre l’écosystème Partisia Blockchain, la fameuse blockchain qui permet de développer des smartcontracts avec une part de confidentialité (une première pour une blockchain qui permet de déployer des smartcontracts).

Je vais donc documenter cette exploration sur plusieurs articles en fonction de mes découvertes.

Dans le premier article disponible en cliquant sur ce lien, nous avons vu comment installer les outils nécessaires au développement, et comment déployer un smartcontract classique.

Dans ce second article, nous allons entrer dans les détails d’un smart contract écrit pour Partisia en Rust.

Tout d’abord il faut savoir qu’un smartcontract se compose de 3 elements : les states, les actions et l’ initializer.

Ces 3 elements se déclarent avec ce qu’on appelle des macros :

  • [#state] : Les états du contract. Peut aussi être compris comme la “base de donnée” de notre smartcontract. C’est là que nous stockerons les données.
  • [#action] : Ce sont end-points pour interagir avec notre smartcontract, à savoir modifier les states.
  • [#init] : La fonction d’initialisation du smartcontract, elle n’est lancée qu’une seule fois : au moment du déploiement du smartcontract et permet notamment d’initialiser les states.

1. State

Dans notre exemple example-token-contract la state ressemble à ceci :

#[state]
pub struct TokenContractState {
  name: String,
  decimals: u8,
  symbol: String,
  owner: Address,
  total_supply: u64,
  balances: BTreeMap<Address, u64>,
  allowed: BTreeMap<Address, BTreeMap<Address, u64>>,
}
Enter fullscreen mode Exit fullscreen mode

À noter qu’il est possible d’ajouter des méthodes à notre state pour pouvoir servir des données plus simplement. Dans notre exemple, nous avons ajouté une implémentation à la struct TokenContractState.

Voici à quoi ça ressemble :

impl TokenContractState {
  pub fn balance_of(&mut self, owner: Address) -> u64 {
    *self.balances.entry(owner).or_insert(0)
  }
  pub fn total_supply(&self) -> u64 {
    self.total_supply
  }
  pub fn allowance(&mut self, owner: Address, spender: Address) -> u64 {
    let allowed_from_owner = self.allowed.entry(owner).or_insert_with(BTreeMap::new);
    let allowance = allowed_from_owner.entry(spender).or_insert(0);
    *allowance
  }
  fn update_allowance(&mut self, owner: Address, spender: Address, value: u64) {
    let allowed_from_owner = self.allowed.entry(owner).or_insert_with(BTreeMap::new);
    allowed_from_owner.insert(spender, value);
  }
}
Enter fullscreen mode Exit fullscreen mode

Pour ceux qui ne connaissent pas Rust, vous noterez que certaines lignes finissent pas ; et d’autres non. Le fait de ne pas terminer la ligne par un ; signifie simplement que l’on retourne la valeur. Ce qui nous permet d’écrire moins de code ;)


2. Action

Comme dit précédemment, les actions servent à modifier nos states.

Dans notre exemple, nous avons l’action transfer qui ressemble à ceci :

#[action]
pub fn transfer(
  context: ContractContext,
  state: TokenContractState,
  to: Address,
  value: u64,
) -> (TokenContractState, Vec<EventGroup>) {
  let mut new_state = state;
  let from_amount = new_state.balance_of(context.sender);
  let o_new_from_amount = from_amount.checked_sub(value);
  match o_new_from_amount {
    Some(new_from_amount) => {
      new_state.balances.insert(context.sender, new_from_amount);
    }
    None => {
      panic!(Underflow in transferowner did not have enough tokens);
    }
  }
  let to_amount = new_state.balance_of(to);
  new_state.balances.insert(to, to_amount.add(value));
  if new_state.balance_of(context.sender) == 0 {
    new_state.balances.remove(&context.sender);
  };
  (new_state, vec![])
}
Enter fullscreen mode Exit fullscreen mode

L’action reçoit en premier argument le context, puis en second argument la state non-modifiable du contract, et ensuite tous les arguments nécessaires à son execution, définis par le développeur.

L’action doit aussi nécessairement retourner la nouvelle state modifiée et un vecteur d’évènements, qui sont une liste d’interactions avec d’autres contracts.

On remarquera que la première instruction dans notre action est let mut new_state = state;. Ici mut nous permet de spécifier que new_state sera mutable, comprendre modifiable, et que new_state se réfère à la state.

C’est cette ligne qui nous permet de modifier la new_state dans les lignes qui suivent, pour au final la retourner à la dernière ligne afin de pouvoir modifier la state du contrat.

Finalement, étant donné que dans ce cas, nous n’interagissons pas avec d’autres smartcontract, nous retournons simplement une liste vide pour le vecteur d’évènement : vec![].


3. Init

La macro [#init] quant à elle se rapproche beaucoup de la macro [#action] à la différence que c’est une action n’a pas d’argument state et que cette action n’est lancée qu’une seule fois : Lors de la création du smartcontract.

Si la fonction init échoue, alors le smartcontract n’est pas créé.

Dans notre exemple, voici à quoi ressemble la fonction d’initialisation :

#[init]
pub fn initialize(
  ctx: ContractContext,
  name: String,
  symbol: String,
  decimals: u8,
  total_supply: u64,
) -> (TokenContractState, Vec<EventGroup>) {
  let mut balances = BTreeMap::new();
  balances.insert(ctx.sender, total_supply);
  let state = TokenContractState {
    name,
    symbol,
    decimals,
    owner: ctx.sender,
    total_supply,
    balances,
    allowed: BTreeMap::new(),
  };
  (state, vec![])
}
Enter fullscreen mode Exit fullscreen mode

Pour en apprendre plus sur Rust, voici un lien intéressant pour les développeurs en reconversion : https://www.educative.io/courses/learn-rust-from-scratch/R1GjgxmKKJw

Pour en savoir plus sur Partisia, voici le lien vers la documentation officielle : https://partisiablockchain.gitlab.io/documentation/

Et si vous voulez, vous pouvez aussi me suivre sur twitter pour des infos plus concises sur Partisia, la blockchain en général et un peu d’économie : https://twitter.com/mehdi_kernel

Top comments (0)