Les Types en Solidity

 

Types de données

Documentation : https://docs.soliditylang.org/en/v0.8.3/types.html

Solidity est un langage typé de manière statique, les types de données doivent être spécifiés.

Types de Valeur

Booléens
De type bool ou les valeurs possibles sont des constantes, true ou false.

Entiers
Le mot-clé int :*désigne un entier signé et uint un entier non signé. La taille de l'entier peut être spécifiée par incrément de 8 (uint8, uint16...) jusqu'a 256. int et uint sont des alias qui font respectivement référence à int256 et uint256.

Obtenir un nombre aléatoire :
https://ethereum.stackexchange.com/questions/191/how-can-i-securely-generate-a-random-number-in-my-smart-contract

Normalement, il n'y a pas d’intérêt à utiliser ces sous-types car Solidity réserve 256 bits de stockage indépendamment de la taille du uint. Par exemple, utiliser un uint8 à la place d'un uint (uint256) ne vous fera pas gagner de gas.

Mais il y a une exception : dans les struct.

Si vous avez plusieurs uint dans une structure, utiliser des plus petits uint quand c'est possible permettra à Solidity d'emboîter ces variables ensemble pour qu'elles prennent moins de place. Par exemple :

struct NormalStruct {
  uint a;
  uint b;
  uint c;
}

struct MiniMe {
  uint32 a;
  uint32 b;
  uint c;
}

MiniMe utilisera moins de gas que `normal` grâce à l’emboîtement de structure

NormalStruct normal = NormalStruct(10, 20, 30);
MiniMe mini = MiniMe(10, 20, 30);

Pour cette raison, à l'intérieur d'une structure, il sera préférable d'utiliser le plus petit sous-type possible.

Il sera aussi important de grouper les types de données (c.-à.-d. les mettre à coté dans la structure) afin que Solidity puisse minimiser le stockage nécessaire. Par exemple, une structure avec des champs uint c; uint32 a; uint32 b; coûtera moins cher qu'une structure avec les champs uint32 a; uint c; uint32 b; car les champs uint32 seront regroupés ensemble.

Mappings et Tableaux

    Zombie[] public zombies;

    mapping (uint => address) public zombieToOwner;
    mapping (address => uint) ownerZombieCount;

Déclarer des tableaux dans la mémoire
Vous pouvez utiliser le mot clé memory avec des tableaux afin de créer un nouveau tableau dans une fonction sans avoir besoin de l'écrire dans le stockage. Le tableau existera seulement jusqu'à la fin de l'appel de la fonction, et cela sera beaucoup plus économique, d'un point de vue du gas, que de mettre à jour un tableau dans storage - c'est gratuit si c'est une fonction view appelée extérieurement.

Voici comment déclarer un tableau dans la mémoire :

function getArray() external pure returns(uint[]) {
// Instancier un nouveau tableau d'une longueur 3 dans la mémoire
uint[] memory values = new uint[](3);
// Lui ajouter des valeurs
values.push(1);
values.push(2);
values.push(3);
// Renvoyer le tableau
return values;
}

Longueur
zombies.length

Unités de Temps

La variable now (maintenant) va retourner l'horodatage actuel unix (le nombre seconde écoulées depuis le 1er janvier 1970). L'horodatage unix au moment où j'écris cette phrase est 1515527488.now renvoie un uint256 par défaut

Remarque : L'horodatage unix est traditionnellement stocké dans un nombre 32-bit. Cela mènera au problème "Année 2038", quand l'horodatage unix 32-bits aura débordé et cassera beaucoup de système existant. Si nous voulons que notre DApp continue de marcher dans 20 ans, nous pouvons utiliser un nombre 64-bit à la place - mais nos utilisateurs auront besoin de dépenser plus de gas pour utiliser notre DApp pendant ce temps. Décision de conception !

Solidity a aussi des unités de temps seconds (secondes), minutes, hours (heures), days (jours) et years (ans). Ils vont se convertir en un uint correspondant au nombre de seconde de ce temps. Donc 1 minutes est 60, 1 hours est 3600 (60 secondes x 60 minutes), 1 days est 86400 (24 heures x 60 minutes x 60 seconds), etc.

Voici un exemple montrant l'utilité de ces unités de temps :

uint lastUpdated;

// Défini `lastUpdated` à `now`
function updateTimestamp() public {
  lastUpdated = now;
}

// Retournera `true` si 5 minutes se sont écoulées
// depuis que `updateTimestamp` a été appelé, `false`
// si 5 minutes ne se sont pas passées
function fiveMinutesHavePassed() public view returns (bool) {
  return (now >= (lastUpdated + 5 minutes));
}

Operators:

Comparisons: <=, <, ==, !=, >=, > (evaluate to bool)
Bit operators: &, |, ^ (bitwise exclusive or), ~ (bitwise negation)
Shift operators: << (left shift), >> (right shift)
Arithmetic operators: +, -, unary - (only for signed integers), *, /, % (modulo), ** (exponentiation)
For an integer type X, you can use type(X).min and type(X).max to access the minimum and maximum value representable by the type.

Operators:

! (logical negation)
&& (logical conjunction, “and”)
|| (logical disjunction, “or”)
== (equality)
!= (inequality)
The operators || and && apply the common short-circuiting rules. This means that in the expression f(x) || g(y), if f(x) evaluates to true, g(y) will not be evaluated even if it may have side-effects.

Libraries
ex safemath

Addresse

Le type address présente deux variantes.
  • address: Holds a 20 byte value (size of an Ethereum address).
  • address payable: Same as address, but with the additional members transfer and send.

Stockage vs mémoire

En Solidity, il y a deux endroits pour stocker les variables - dans le storage (stockage) ou dans la memory (mémoire).

contract SandwichFactory {
  struct Sandwich {
    string name;
    string status;
  }

  Sandwich[] sandwiches;

  function eatSandwich(uint _index) public {
    // Sandwich mySandwich = sandwiches[_index];

    // ^ Cela pourrait paraître simple, mais Solidity renverra un avertissement
    // vous indiquant que vous devriez déclarer explicitement `storage` ou `memory` ici.

    // Vous devriez donc déclarez avec le mot clé `storage`, comme ceci :
    Sandwich storage mySandwich = sandwiches[_index];

    // ...dans ce cas, `mySandwich` est un pointeur vers `sandwiches[_index]`
    // dans le stockage et...
    mySandwich.status = "Eaten!";

    // ... changera définitivement `sandwiches[_index]` sur la blockchain.

    // Si vous voulez juste une copie, vous pouvez utiliser `memory`:
    Sandwich memory anotherSandwich = sandwiches[_index + 1];
    // ...dans ce cas, `anotherSandwich` sera simplement une copie des
    // données dans la mémoire et...
    anotherSandwich.status = "Eaten!";
    // ... modifiera simplement la variable temporaire et n'aura pas
    // d'effet sur `sandwiches[_index + 1]`. Mais vous pouvez faire ceci :
    sandwiches[_index + 1] = anotherSandwich;
    // ...si vous voulez copier les modifications dans le stockage de la blockchain.
  }
}

Commentaires

Posts les plus consultés de ce blog

Sécurité des Applications

Principes de la Programmation Orientée Objet

Principe de Responsabilité Unique