Introduction
C’est la deuxième partie de la série d’examens de contrats en direct et aujourd’hui, nous allons examiner le contrat de pool de staking, qui est utilisé en ce moment pour sécuriser le protocole NEAR.système de preuve de mise. Fondamentalement, tous les validateurs qui fonctionnent actuellement sur le protocole NEAR fonctionnent au nom de ce contrat. Ils ne contrôlent pas eux-mêmes le compte qui mise le montant de jetons NEAR requis pour la preuve de mise, mais à la place, le contrat mise ce montant, et ils fournissent simplement un pool de mise et exécutent leurs nœuds. Aujourd’hui, nous allons creuser dans ce contrat. Dans les contrats de base, nous avons un contrat de pool de jalonnement et c’est un peu plus compliqué que le contrat précédent que nous avons examiné (le contrat de vote). Donc, aujourd’hui, nous allons nous concentrer davantage sur la logique et moins sur les éléments spécifiques de near_bindgen et Rust, mais cela impliquera probablement un peu plus de connaissances sur le protocole NEAR. Voici le contrat de pool de staking sur le NEAR Github. Vous trouverez ci-dessous la vidéo originale sur laquelle ce guide est basé.
lib.rs
Structure du constructeur
Comme auparavant, le contrat commence à partir de la structure principale. Dans ce cas, il s’agit d’une structure de contrat de jalonnement. Comme vous pouvez le voir, il y a near_bindgen, et BorshSerialize et BorshDeserialize. La structure a maintenant beaucoup plus de champs que la précédente, et il y a quelques commentaires sur eux, la plupart d’entre eux sont probablement à jour. La logique du contrat de pool de staking nous permet de faire ce qui suit : fondamentalement, n’importe qui peut déposer une certaine quantité de jetons NEAR dans le pool de staking et les déléguer au pool de staking en les mettant dans le pool. Cela nous permet de regrouper les soldes de plusieurs personnes (nous les appelons comptes ici) en un seul gros enjeu, et de cette façon, ce grand État peut en fait se qualifier pour des sièges de validateur. NEAR Protocol a actuellement un nombre limité de sièges pour un seul fragment, il y a au plus 100 sièges de validateur. Vous pouvez penser aux sièges de la manière suivante : si vous prenez le montant total de jetons mis en jeu et que vous le divisez par 100, le résultat sera le nombre minimum de jetons requis pour un seul siège, sauf que c’est un peu plus compliqué d’impliquer le retrait les enjeux qui ne sont pas qualifiés pour contenir ce montant minimum, etc. Ce contrat est essentiellement un contrat autonome sans aucune clé d’accès qui est contrôlé par le propriétaire. Dans ce cas, le propriétaire est fourni dans la méthode d’initialisation. Ce contrat est essentiellement un contrat autonome sans clé d’accès qui est contrôlé par le propriétaire. Dans ce cas, le propriétaire est fourni dans la méthode d’initialisation. Ce contrat est essentiellement un contrat autonome sans clé d’accès qui est contrôlé par le propriétaire. Dans ce cas, le propriétaire est fourni dans la méthode d’initialisation.
Méthode d’initialisation
Passons donc à la méthode d’initialisation. Il a trois arguments et le premier est le owner_id qui est l’identifiant du compte du propriétaire. Le propriétaire a un tas d’autorisations sur ce contrat qui permettent au contrat d’effectuer des actions qui ne sont pas disponibles pour le reste des comptes. L’une de ces méthodes consistait à voter au nom du pool de jalonnement sur le contrat de vote dont nous avons discuté la dernière fois. Ainsi, le propriétaire peut appeler la méthode de vote.
Nous vérifions ensuite que le prédécesseur est égal au propriétaire puisque cette méthode ne peut être appelée que par le propriétaire.
Donc, ce que fait la méthode de vote, c’est qu’elle vérifie que la méthode n’a été appelée que par le propriétaire, puis elle vérifie une certaine logique, mais ce n’est pas important pour le moment.
Le contrat est donc le propriétaire, et ce propriétaire peut faire certaines choses, il a les autorisations supplémentaires. Ensuite, cela prend quelques champs supplémentaires : cela prend la clé_public_enjeu. Lorsque vous misez sur le protocole NEAR, vous devez fournir une clé publique qui sera utilisée par votre nœud de validation pour signer des messages au nom du nœud de validation. Cette clé publique peut être différente de n’importe quelle clé d’accès, et idéalement, elle devrait être différente de toute clé d’accès, car votre nœud peut être exécuté dans un centre de données susceptible d’être vulnérable à certaines attaques. Dans ce cas, le mieux qu’ils puissent faire est de faire quelque chose de mal au réseau, mais pas à votre compte. Ils ne peuvent pas voler vos fonds et vous pouvez facilement remplacer cette clé par rapport à la façon dont vous devez remplacer la mauvaise clé d’accès. Enfin, le troisième argument pris en charge par le contrat est la fraction_frais_récompense initiale. Il s’agit de la commission que le propriétaire du pool de jalonnement prend pour exécuter le nœud de validation.
Il s’agit d’une fraction qui a un numérateur et un dénominateur, et elle vous permet essentiellement de dire “Je prends 1% des récompenses pour l’exécution de ce pool particulier”, par exemple. Disons que vous avez 1 000 000 de jetons, ils ont acquis une récompense, disons qu’il y a une récompense de 10 000 jetons, alors le propriétaire en retirera 1%, soit 100 jetons. Les flotteurs ont un comportement imprévisible lorsque vous les multipliez. Par exemple, avec des fractions, vous pouvez utiliser des mathématiques avec un plus grand nombre de bits. Ainsi, la façon dont vous faites la division, par exemple, consiste à multiplier d’abord le montant qui est u128 par un numérateur (cela peut déjà déborder dans u128), mais c’est pourquoi nous le faisons dans u256. Ensuite, vous le divisez par le dénominateur qui devrait le ramener en dessous de u128. Cela vous donne une précision plus élevée que float64 qui ne peut pas fonctionner avec une précision u128 bits, il y aura donc des erreurs d’arrondi ou des erreurs de précision lorsque vous faites le calcul. Donc, vous avez besoin de flotteurs de plus haute précision, qui ne sont pas vraiment différents des mathématiques où nous simulons cela avec u256. À l’origine, Solidity ne prenait pas en charge les flottants, et nous ne l’avons pas fait non plus à l’origine, mais cela pose des problèmes de formatage des chaînes dans Rust pour le débogage. Le plus gros problème avec les flotteurs était le comportement indéfini autour de certaines valeurs de charges. Par exemple, ce que contiennent les autres bits lorsque vous avez un flottant infini. Nous avons standardisé cela, et maintenant ils sont indépendants de la plate-forme équivalente. Il est donc possible d’utiliser des flottants maintenant dans notre environnement vm. qui ne sont pas vraiment différents des maths où nous simulons cela avec u256. À l’origine, Solidity ne prenait pas en charge les flottants, et nous ne l’avons pas fait non plus à l’origine, mais cela pose des problèmes de formatage des chaînes dans Rust pour le débogage. Le plus gros problème avec les flotteurs était le comportement indéfini autour de certaines valeurs de charges. Par exemple, ce que contiennent les autres bits lorsque vous avez un flottant infini. Nous avons standardisé cela, et maintenant ils sont indépendants de la plate-forme équivalente. Il est donc possible d’utiliser des flottants maintenant dans notre environnement vm. qui ne sont pas vraiment différents des maths où nous simulons cela avec u256. À l’origine, Solidity ne prenait pas en charge les flottants, et nous ne l’avons pas fait non plus à l’origine, mais cela pose des problèmes de formatage des chaînes dans Rust pour le débogage. Le plus gros problème avec les flotteurs était le comportement indéfini autour de certaines valeurs de charges. Par exemple, ce que contiennent les autres bits lorsque vous avez un flottant infini. Nous avons standardisé cela, et maintenant ils sont indépendants de la plate-forme équivalente. Il est donc possible d’utiliser des flottants maintenant dans notre environnement vm. nous avons donc décidé qu’il n’y avait aucun mal à prendre en charge les flotteurs, d’autant plus que nous standardisons cela du côté vm. Le plus gros problème avec les flotteurs était le comportement indéfini autour de certaines valeurs de charges. Par exemple, ce que contiennent les autres bits lorsque vous avez un flottant infini. Nous avons standardisé cela, et maintenant ils sont indépendants de la plate-forme équivalente. Il est donc possible d’utiliser des flottants maintenant dans notre environnement vm. nous avons donc décidé qu’il n’y avait aucun mal à prendre en charge les flotteurs, d’autant plus que nous standardisons cela du côté vm. Le plus gros problème avec les flotteurs était le comportement indéfini autour de certaines valeurs de charges. Par exemple, ce que contiennent les autres bits lorsque vous avez un flottant infini. Nous avons standardisé cela, et maintenant ils sont indépendants de la plate-forme équivalente. Il est donc possible d’utiliser des flottants maintenant dans notre environnement vm.
La pratique standard avec init est que nous vérifions d’abord que l’état n’existe pas. Ensuite, nous vérifions l’entrée. La première chose que nous faisons est de vérifier que la fraction est valide et de vérifier que le dénominateur n’est pas zéro. Ensuite, nous avons une instruction else qui vérifie que le numérateur est inférieur ou égal au dénominateur, ce qui signifie que la fraction est inférieure ou égale à 1. Ceci est important pour éviter certaines erreurs de logique. La prochaine chose que nous faisons est de vérifier que le compte est valide. Ce contrat a été rédigé avant certaines des métriques d’aide qui existent maintenant. Par exemple, nous avons l’identifiant de compte valide dans les types JSON qui effectue cette vérification automatiquement lors de la désérialisation, s’il n’est pas valide, il ne fera que paniquer. Après cela, nous tirons le solde du compte courantdu contrat de jalonnement. Ce solde est généralement assez important car il doit payer pour le stockage de ce contrat particulier, puis nous disons que nous allons allouer des jetons pour le STAKE_SHARE_PRICE_GUARANTEE_FUND. Le pool de jalonnement a certaines garanties qui sont importantes pour les contrats locaux. Les garanties garantissent que lorsque vous déposez dans le pool de jalonnement, vous devriez pouvoir retirer au moins le même nombre de jetons, et vous ne pouvez pas perdre de jetons même pour 1 000 000 000 000 yocto NEAR sur ce contrat en déposant et en retirant de les piscines de jalonnement. Le fonds STAKE_SHARE_PRICE_GUARANTEE_FUND est d’environ 1 000 milliards de yocto NEAR, alors que nous consommons généralement environ 1 ou 2 000 milliards de yocto NEAR pour les erreurs d’arrondi. Enfin on se rappelle quel est le solde que l’on va miser au nom de ce contrat. Ceci est nécessaire pour établir une base de référence afin de limiter les différences d’arrondi. Ensuite, nous vérifions que le compte n’a pas déjà jalonné. Cela pourrait briser une certaine logique. Nous ne voulons pas que cela se produise, nous voulons donc initialiser le contrat avant qu’il ne mette quoi que ce soit. Enfin, nous initialisons la structure, mais nous ne la retournons pas immédiatement. Nous venons de créer la structure StakingContract ici.
Ensuite, nous émettons une transaction de reprise. Ceci est important, car nous devons nous assurer que cette clé de jalonnement qui a été fournie est une clé restreinte ristretto valide, par exemple, une clé valide 5 119. Certaines clés sur la courbe sont des clés valides, mais ne sont pas spécifiques à un ristretto, et les clés de validation ne peuvent être spécifiques qu’à un ristretto. C’est une chose spécifique au protocole NEAR, et ce qui se passe, c’est qu’il effectue une transaction de jalonnement avec la clé donnée. Une fois cette transaction créée à partir du contrat, nous validons cette transaction à sa sortie. Si la clé n’est pas valide, elle générera une erreur et toute l’initialisation de ce pool de jalonnement échouera. Si vous transmettez une clé publique_enjeu invalide en entrée, la consolidation et le déploiement de votre contrat, et toutqui se produit dans cette transaction par lot sera annulée. Ceci est important pour que le pool n’ait pas de clé invalide, car cela pourrait vous permettre de bloquer la mise d’autres personnes. Dans le cadre des garanties, nous disons que si vous annulez votre mise, vos jetons seront rendus en 4 époques. Ils seront éligibles au retrait, et c’est important pour pouvoir les remettre en détention.
Je pense que c’est trop de détails avant d’expliquer la vue d’ensemble de haut niveau sur le fonctionnement des contrats et le fonctionnement des soldes. Expliquons le concept de la façon dont nous pouvons réellement distribuer des récompenses aux propriétaires de compte en temps constant lorsqu’une époque passe. Ceci est important pour la plupart des contrats intelligents. Ils veulent agir en temps constant pour chaque méthode au lieu d’un temps linéaire pour le nombre d’utilisateurs, car si le nombre d’utilisateurs augmente, la quantité de gaz nécessaire pour faire fonctionner une échelle linéaire augmentera également, et elle finira par manquer de gaz. C’est pourquoi tous les contrats intelligents doivent agir en temps constant.
Structure du compte
La façon dont cela fonctionne pour chaque utilisateur, nous gardons la structure appelée compte. Chaque utilisateur qui a délégué à ce pool de jalonnement aura une structure appelée compte qui ales champs suivants : unstaked est le solde dans yocto NEAR qui n’est pas jalonné donc c’est juste le solde de l’utilisateur. Ensuite, stake_shares est en fait un solde, mais pas en NEAR, mais plutôt en nombre de parts de jeu. Stake_shares est un concept qui a été ajouté à ce pool de jalonnement particulier. La façon dont cela fonctionne est que lorsque vous misez, vous achetez essentiellement de nouvelles actions au prix actuel en convertissant votre solde de mise en jeu en actions. Le prix d’une part de participation est à l’origine 1, mais au fil du temps, il augmente avec les récompenses, et lorsque le compte reçoit des récompenses, son solde de participation totale augmente, mais le montant total des actions de participation ne change pas. Essentiellement, lorsqu’un compte reçoit des récompenses de validation ou d’autres dépôts directement sur le solde, cela augmente le montant que vous pouvez recevoir pour chaque part de participation. Disons, par exemple, vous aviez à l’origine 1 million NEAR qui a été déposé sur ce compte. Disons que vous obtenez 1 million de parts (en ignorant le yocto NEAR pour l’instant), si le staking pool a reçu 10 000 NEAR en récompenses, vous avez toujours 1 million de parts, mais le 1 million de parts correspond désormais à 1 010 000 NEAR. Maintenant, si quelqu’un d’autre veut participer à ce moment-là, il achètera des parts de participation en interne dans le cadre du contrat.au prix de 1,001 NEAR, parce que chaque action en vaut la peine maintenant. Lorsque vous recevez une autre récompense, vous n’avez pas besoin d’acheter plus d’actions malgré le solde total, et dans le temps constant , tout le monde partage la récompense proportionnellement au nombre d’actions qu’il possède. Maintenant, lorsque vous annulez votre participation, vous vendez essentiellement ces actions ou les brûlez en utilisant le concept de jetons fongibles en faveur du solde non jalonné. Ainsi, vous vendez au prix actuel, vous diminuez le montant total de la mise ainsi que le montant total des actions, et lorsque vous achetez, vous augmentez le solde total de la mise et le total des actions tout en maintenant le prix constant. Lorsque vous misez ou désengagez, vous ne changez pas le prix, lorsque vous recevez les récompenses, vous augmentez le prix.
Le prix ne peut que monter, et cela peut conduire à des erreurs d’arrondi lorsque votre yocto NEAR et votre solde ne peuvent pas correspondre précisément. C’est pourquoi nous avons ce fonds de garantie de 1 000 milliards de yocto NEAR qui jettera plusieurs fois un yocta NEAR supplémentaire dans le mélange. Enfin, la dernière partie est là, parce que le protocole NEAR ne débloque pas et ne restitue pas le solde immédiatement, il doit attendre trois époques jusqu’à ce que votre solde soit débloqué et retourné sur le compte. Si vous annulez votre mise, vous ne pouvez pas retirer ce solde immédiatement du pool de mise, vous devez attendre trois époques. Ensuite, vous vous souvenez à quelle hauteur d’époque vous avez appelé la dernière action de désengagement, et après trois époques, votre équilibre sera déverrouillé et vous devriez être en mesure de vous retirer du désengagement. Cependant, il y a une mise en garde : si vous annulez la mise au dernier bloc de l’époque, la promesse réelle qui fait le dépouillement arrivera pour la prochaine époque. Il arrivera au premier bloc de l’époque suivante, et cela retardera le déblocage de votre solde verrouillé à quatre époques au lieu de trois. C’est parce que nous avons enregistré l’époque dans le précédentbloc, mais la transaction réelle s’est produite dans le bloc suivant, à l’époque suivante. Pour s’assurer que cela n’arrive pas, nous bloquons l’équilibre par quatre époques au lieu de trois époques pour tenir compte de ce cas limite. C’est ce qui constitue un compte. L’idée des actions n’est pas si nouvelle, car sur Ethereumla majorité des fournisseurs de liquidité et des teneurs de marché automatisés utilisent ce concept similaire. Lorsque vous effectuez, par exemple, un dépôt dans le pool de liquidités, vous obtenez une sorte de jeton de ce pool au lieu du montant réel qui y est représenté. Lorsque vous vous retirez du pool de liquidités, vous brûlez ce jeton et obtenez les jetons réellement représentés. L’idée est très similaire au fait de les appeler actions, car elles ont un prix correspondant, et nous aurions pu les appeler différemment. C’était presque depuis le début de ce contrat de pool de jalonnement. Nous avons exploré comment nous pouvons le faire correctement, et l’une des solutions consistait à limiter le nombre de comptes pouvant être déposés sur un compte de pool donné pour cette mise à jour particulière. Nous avons finalement atterri sur le temps de complexité constant et c’était en fait un modèle plus simple.
Types de contrat
Passons en revue ce contrat. Ce n’est pas aussi bien structuré qu’un contrat de lock-up par exemple, car le lock-up est encore plus compliqué. Les types sont toujours regroupés dans le même contrat. Il existe de nombreux types de types, par exemple, reward_fee_fraction est un type distinct.
Le compte est un type distinct et il existe également un compte lisible par l’homme qui est également un type qui n’est utilisé que pour les appels de vue, il n’est donc pas utilisé pour la logique en interne.
Ensuite, après avoir terminé avec tous les types, nous avons des appels de contrats croisés utilisant une interface de haut niveau.
Il y en a deux. La façon dont cela fonctionne est que vous avez une macro de near_bindgen appelée ext_contract (pour contrat externe). Vous pouvez lui donner un nom court qu’il générera et que vous pourrez utiliser. Ensuite, vous avez une description de trait décrivant l’interface du contrat externe que vous souhaitez utiliser. Cela décrit le fait que vous pouvez appeler une méthode de vote sur un contrat distant et passer un argument. L’argument is_vote qui est un booléen vrai ou faux. Vous pourrez désormais créer une promesse lorsque vous en aurez besoin et passer un argument positionnel au lieu d’un argument sérialisé JSON. La macro en fera une promesse de bas niveau dans les coulisses. La deuxième interface est pour un rappel sur nous-mêmes, c’est assez courant, vous pouvez l’appeler ext_self. Lorsque vous devez effectuer un rappel, et faire quelque chose sur le résultat de la promesse asynchrone que vous pouvez avoir ce type d’interface. Ce que nous faisons, c’est vérifier si l’action de jalonnement a réussi. Enfin, nous avons cette structure de mise en œuvre principale organe de mise en œuvre du pool de jalonnement.
Structure de fichier de contrat
Ce contrat est divisé en plusieurs modules.
Vous avez libs.rs qui est l’entrée principale, et vous avez également un module interne. Le module interne a l’implémentation sans la macro near_bindgen, donc aucune de ces méthodes ne sera visible pour être appelée par un contrat par quelqu’un d’autre sur la chaîne. Ils ne peuvent être appelés qu’au sein de ce contrat en interne afin qu’ils ne génèrent pas de formats JSON et ne désérialisent pas l’état. Ils agissent tous comme des méthodes de rouille régulières. Le fonctionnement de ce contrat de haut niveau est que lorsqu’une époque passe, vous pouvez acquérir certaines récompenses en tant que validateur.
Méthodes importantes du contrat
Nous avons une méthode ping qui ping le contrat. La méthode ping vérifie si une époque est passée et nous devons ensuite distribuer des récompenses. Si l’époque a changé, elle sera également relancée, car il pourrait y avoir un changement dans le montant de la mise totale que le contrat doit miser. Le prochain est le dépôt.
La méthode de dépôt est payable, ce qui signifie qu’elle peut accepter un dépôt joint. Ceci est similaire au décorateur Ethereum qui vous permet de recevoir des fonds uniquement aux méthodes qui les attendent. Ainsi, par défaut, near_bindgen paniquera si vous essayez d’appeler une méthode, par exemple ping, et attachez un dépôt à cette méthode. Par conséquent, payable nous permet de joindre des acomptes. Dans chaque méthode, il y a un ping interne pour s’assurer que nous avons distribué les récompenses précédentes avant de changer de logique. La structure commune est que si nous devons refaire, nous faisons d’abord une logique, puis nous reprenons.
La méthode suivante est deposit_and_stake. Il s’agit d’une combinaison entre deux méthodes. Tout d’abord, vous déposez le solde sur le solde de mise de votre compte et vous souhaitez également miser le même montant immédiatement au lieu de faire deux transactions. Il est également payable car il accepte également un acompte.
Le suivant est remove_all. Il essaie de retirer la totalité du solde non engagé du compte qui l’a appelé. Lorsque vous interagissez avec le pool de jalonnement, vous devez interagir avec le compte qui détient le solde. Dans ce cas, il s’agit du prédécesseur_account_id et nous vérifions essentiellement le compte, puis nous retirons le montant non misé si nous le pouvons. S’il n’est pas retiré, alors il paniquera. Par exemple, s’il est toujours verrouillé en raison d’un dépilage il y a moins de 4 époques.
Le retrait vous permet de ne retirer que le solde partiel.
Ensuite, stake_all met tout le solde non mis en jeu, et il est assez rare d’utiliser cette méthode, car vous utilisez généralement la mise de dépôt, et il a déjà tout le solde de la mise.
Ensuite, dans la méthode de mise, vous misez simplement un certain montant du solde de la mise. Le portefeuille Moonlight utilise un coût séparé pour déposer en mise, mais ils utilisent une transaction par lots pour ce faire.
Enfin, vous avez unstake_all qui dépouille essentiellement toutes vos parts de participation en les convertissant en yocto NEAR. Il existe une méthode d’aide qui dit de convertir mon nombre d’actions en un montant de yocto NEAR et d’arrondir à l’inférieur, car nous ne pouvons pas vous donner un supplément pour votre action multipliée par le prix. C’est ainsi que nous obtenons le montant, puis nous appelons unstake pour le montant donné.
La logique staked_amount_from_num_shares_ rounded_down utilise u256, car les soldes fonctionnent sur u128. Pour éviter les débordements, nous multiplions le total_staked_balance par le nombre de partages dans u256. Le prix est le quotient arrondi à l’inférieur.
La version arrondie staked_amount_from_num_shares_rounded_up est très similaire sauf que nous effectuons une vérification qui nous permet d’arrondir. À la fin des deux, nous l’avons renvoyé à u128.
Ensuite, nous avons une action de désengagement qui est très similaire à unstake_all, sauf que vous passez le montant.
Méthodes Getter/View
Après cela, il existe un tas de méthodes getter qui sont des appels de vue qui vous renvoient des montants. Vous pouvez obtenir le solde non jalonné du compte, le solde jalonné du compte, le solde total du compte, vérifier si vous pouvez retirer, le solde total de l’enjeu, qui est le montant total que le pool de jalonnement a en jeu actif.
Ensuite, vous pouvez savoir qui est le propriétaire du pool de jalonnement, vous pouvez obtenir les frais de récompense ou la commission actuels du pool de jalonnement, obtenir la clé de jalonnement actuelle, et il y a une chose distincte qui vérifie si le propriétaire a suspendu le pool de jalonnement.
Supposons que le propriétaire effectue une migration sur le pool de jalonnement sur le nœud. Ils doivent complètement débloquer, donc par exemple, ils peuvent mettre en pause le pool de staking qui enverra une transaction d’état au protocole NEAR, puis ne reprendra pas jusqu’à ce qu’ils reprennent le pool de staking. Cependant, vous pouvez toujours retirer vos soldes, mais vous cesserez d’acquérir des récompenses après son expiration.
Enfin, vous pouvez obtenir un compte lisible par l’homme qui vous donne le nombre de jetons que vous avez réellement pour le nombre d’actions au prix actuel, et enfin il indique si vous pouvez retirer ou non.
Ensuite, il vous donne le nombre de comptes qui est le nombre de délégants à ce pool de jalonnement, et vous pouvez également récupérer plusieurs délégants à la fois. Il s’agit de la pagination sur un grand nombre de comptes au sein de la carte non ordonnée. Une façon de le faire est d’utiliser l’assistant que nous appelons keys_as a_vector à partir de la carte non ordonnée. Il vous donne une collection persistante de clés de la carte, puis vous pouvez utiliser un itérateur pour demander des comptes à partir de ces clés. Ce n’est pas le moyen le plus efficace, mais cela vous permet d’implémenter la pagination sur des cartes non ordonnées.
Méthodes du propriétaire
Il existe un tas de méthodes de propriétaire. Une méthode propriétaire est une méthode qui ne peut être appelée que par le propriétaire. Le propriétaire peut mettre à jour la clé de jalonnement. Disons qu’ils ont un nœud différent et que le propriétaire doit utiliser une clé différente. Toutes ces méthodes vérifient d’abord que seul le propriétaire peut l’appeler.
C’est la méthode qui modifie la commission sur le pool de jalonnement. Le propriétaire peut modifier immédiatement la commission qui sera active à cette époque à partir de cette époque, mais toutes les commissions précédentes seront calculées en utilisant les frais précédents.
Ensuite, c’est la méthode de vote qui nous a permis de passer à la phase deux du réseau principal.
Viennent ensuite les deux méthodes que j’ai déjà décrites qui permettent de suspendre le jalonnement et de reprendre le jalonnement.
Le reste ne sont que des tests. La plupart de la logique se passe dans les internes.
Test de simulation
Nous avons aussi essentiellement des tests de simulation pour une piscine particulière. Ce test de simulation montre comment le réseau va réellement fonctionner. Nous avons d’abord initialisé le pool.
Bob est le délégant. Bob a appelé la méthode de dépôt de pool qui est le deposit_amount en utilisant la méthode de dépôt. Ensuite, Bob peut vérifier que le solde non jalonné fonctionne correctement. Ensuite, Bob mise le montant. Ensuite, nous vérifions le montant de la mise maintenant. Nous avons vérifié que Bob a misé le même montant.
Bob appelle la méthode ping. Il n’y a pas de récompenses, mais dans les simulations, les récompenses ne fonctionnent pas de toute façon, vous devez donc le faire manuellement. Nous allons vérifier une fois de plus que le montant de Bob est toujours le même. Puis la piscine reprend. Nous vérifions que le pool a repris, puis verrouillons à zéro. Ensuite, nous simulons que le pool a acquis des récompenses (1 NEAR) et bob ping le pool. Ensuite, nous vérifions que le montant que Bob a reçu est positif. C’est un cas de simulation très simple qui dit que Bob a d’abord déposé dans le pool qui vérifie que la pause et la reprise fonctionnent, ou simule que cela fonctionne et s’assure que le pool ne joue pas pendant la pause. Puis lorsqu’elle est reprise, la piscine mise réellement. Donc, ce test vérifie non seulement cela, mais aussi que Bob a acquis la récompense et s’est fait distribuer la récompense. Il y a un autre test qui vérifie certainslogique mais c’est plus compliqué. Il y a des tests unitaires au bas de celui-ci qui sont censés vérifier certaines choses.
Certains de ces tests ne sont pas idéaux, mais ils vérifient certaines choses qui étaient assez bonnes pour s’assurer que les mathématiques s’additionnent.
internal.rs
Méthode de ping internal
Passons à internal_ping. C’est la méthode que n’importe qui peut appeler via ping pour s’assurer que les récompenses sont distribuées. À l’heure actuelle, nous avons des pools de jalonnement actifs et il y a un compte parrainé par l’un des membres de NEAR qui envoie un ping à chaque mise du pool toutes les 15 minutes pour s’assurer qu’ils ont distribué les récompenses à afficher sur le solde. De cette façon, la distribution des récompenses fonctionne. Nous vérifions d’abord la hauteur de l’époque actuelle, donc si la hauteur de l’époque est la même, alors l’époque n’a pas changé, nous renvoyons false afin que vous n’ayez pas besoin de refaire. Si l’époque a changé alors nousrappelez-vous que l’époque actuelle (hauteur de l’époque) existe, nous obtenons le nouveau solde total du compte. Le ping peut être appelé lorsque certains jetons ont été déposés via des bulletins de dépôt, et ils font déjà partie du compte_balance, et comme le ping a été appelé avant, nous devons soustraire ce solde avant de distribuer les récompenses. Nous obtenons le montant total du compte, y compris le solde bloqué et le solde débloqué. Le solde verrouillé est un montant misé qui acquiert des récompenses, et le solde déverrouillé peut également avoir des récompenses dans certains scénarios où vous diminuez votre mise, mais vos récompenses seront toujours reflétées pour les deux prochaines époques. Après cela, ils viendront au montant non misé. Nous vérifions en utilisant assert! que le solde total est supérieur au solde total précédent. C’est un invariant que requiert le pool de jalonnement. Il y avait un tas de trucs sur le testnet qui ont échoué à cet invariant parce que les gens avaient toujours des clés d’accès sur le même pool de jalonnement, et quand vous l’avez, vous dépensez le solde pour l’essence, et vous pouvez diminuer votre solde total sans acquérir la récompense . Enfin, nous calculons le montant des récompenses que le pool de staking a reçu. Il s’agit du solde total moins le solde total connu précédent, le solde de l’époque précédente. Si les récompenses sont positives, nous le solde de l’époque précédente. Si les récompenses sont positives, nous le solde de l’époque précédente. Si les récompenses sont positives, nousles distribuer. La première chose que nous faisons est de calculer la récompense que le propriétaire prend pour lui-même sous forme de commission.
Nous multiplions la reward_fee_fraction par la récompense totale reçue et celle-ci est arrondie de la même manière avec le numérateur en u256 multiplié par la valeur divisée par le dénominateur en u256.
Le owner_fee est le montant en yocto NEAR que le propriétaire gardera pour lui-même. Le restant_reward correspond aux récompenses restantes qui doivent être réinvesties. Ensuite, il est refait. Le propriétaire a reçu les récompenses dans yocta NEAR, pas en actions, mais parce que toute la logique doit être en actions, le propriétaire du pool de jalonnement achète des actions au prix des distributions post-récompenses au reste des délégants. Donc, num_shares est le nombre d’actions que le propriétaire recevra en compensation pour la gestion du pool de jalonnement. S’il est positif, nous augmentons le nombre d’actions et économisons le compte du propriétaire, et nous augmentons également le montant total de la participation en actions. Si, pour une raison quelconque, lors de l’arrondissement, ce solde devenait nul, la récompense était très faible et le prix par action était très élevé, et le pool ne recevait que zéro récompense. Dans ce cas, ce solde ira simplement au prix par action au lieu d’indemniser le propriétaire. Ensuite, nous mettons des données de journalisation totales indiquant que l’époque actuelle existe, que nous avons reçu les récompenses en un nombre de parts de jalonnement ou de jetons, que le solde total de la participation du pool est quelque chose, et nous enregistrons le nombre de parts. La seule façon d’exposer le nombre de partages au monde extérieur est à travers les journaux. Ensuite, si le propriétaire a reçu des récompenses, cela signifie que la récompense totale était autant d’actions. Enfin, on se souvient juste du nouveau solde total et c’est tout. Nous avons distribué toutes les récompenses en temps constant et nous n’avons mis à jour qu’un seul compte (compte du propriétaire) pour la commission, et uniquement si la commission était positive. nous mettons des données de journalisation totales qui indiquent que l’époque actuelle existe, que nous avons reçu les récompenses en un nombre d’actions de jalonnement ou de jetons, que le solde total de la mise du pool est quelque chose, et nous enregistrons le nombre d’actions. La seule façon d’exposer le nombre de partages au monde extérieur est à travers les journaux. Ensuite, si le propriétaire a reçu des récompenses, cela signifie que la récompense totale était autant d’actions. Enfin, on se souvient juste du nouveau solde total et c’est tout. Nous avons distribué toutes les récompenses en temps constant et nous n’avons mis à jour qu’un seul compte (compte du propriétaire) pour la commission, et uniquement si la commission était positive. nous mettons des données de journalisation totales qui indiquent que l’époque actuelle existe, que nous avons reçu les récompenses en un nombre d’actions de jalonnement ou de jetons, que le solde total de la mise du pool est quelque chose, et nous enregistrons le nombre d’actions. La seule façon d’exposer le nombre de partages au monde extérieur est à travers les journaux. Ensuite, si le propriétaire a reçu des récompenses, cela signifie que la récompense totale était autant d’actions. Enfin, on se souvient juste du nouveau solde total et c’est tout. Nous avons distribué toutes les récompenses en temps constant et nous n’avons mis à jour qu’un seul compte (compte du propriétaire) pour la commission, et uniquement si la commission était positive. La seule façon d’exposer le nombre de partages au monde extérieur est à travers les journaux. Ensuite, si le propriétaire a reçu des récompenses, cela signifie que la récompense totale était autant d’actions. Enfin, on se souvient juste du nouveau solde total et c’est tout. Nous avons distribué toutes les récompenses en temps constant et nous n’avons mis à jour qu’un seul compte (compte du propriétaire) pour la commission, et uniquement si la commission était positive. La seule façon d’exposer le nombre de partages au monde extérieur est à travers les journaux. Ensuite, si le propriétaire a reçu des récompenses, cela signifie que la récompense totale était autant d’actions. Enfin, on se souvient juste du nouveau solde total et c’est tout. Nous avons distribué toutes les récompenses en temps constant et nous n’avons mis à jour qu’un seul compte (compte du propriétaire) pour la commission, et uniquement si la commission était positive.
Méthode de internal stake
L’internal_stake est l’endroit où nous mettons en œuvre le fonds de garantie des prix. Disons que le prédécesseur, dans ce cas, nous allons l’appeler account_id veut miser un nombre de jetons. Balance n’est en fait pas un type JSON, car il s’agit d’une méthode interne, nous n’avons donc pas besoin de JSON ici. Nous calculons combien d’actions sont arrondies à l’inférieur qui sont nécessaires pour miser le montant donné, c’est donc le nombre d’actions que le propriétaire recevra. Il doit être positif. Ensuite, nous vérifions le montant que le propriétaire doit payer pour les actions, encore une fois arrondi à l’inférieur. C’est pour garantir que lorsque le propriétaire a acheté des actions et les a reconverties sans récompenses, il n’a jamais perdu le 1 yocto NEAR, car cela pourrait rompre la garantie. Enfin, nous affirmons que le compte a assez pour payer le montant facturé, et nous diminuons le solde interne non mis en jeu, et augmenter le solde interne du nombre d’actions du compte. Ensuite, nous arrondissons le staked_amount_from_num_shares_rounded_up vers le haut afin que le nombre d’actions soit réellement arrondi. Ce 1 penny supplémentaire ou 1 yocto supplémentaire NEAR proviendra du fonds garanti lors de l’arrondi des actions. Nous avons facturé moins à l’utilisateur, mais nous avons contribué davantage au montant de ce 1 000 milliards de yocto NEAR que nous avions initialement désigné pour cela. Cette différence n’est généralement que de 1 yocto NEAR qui peut provenir de l’arrondi vers le haut ou vers le bas. Après cela, il y a le montant de total_staked_balance et total_stake_shares. Ensuite, nous créons de nouvelles actions avec eux. Enfin, nous mettons un journal et retournons le résultat. Ce 1 penny supplémentaire ou 1 yocto supplémentaire NEAR proviendra du fonds garanti lors de l’arrondi des actions. Nous avons facturé moins à l’utilisateur, mais nous avons contribué davantage au montant de ce 1 000 milliards de yocto NEAR que nous avions initialement désigné pour cela. Cette différence n’est généralement que de 1 yocto NEAR qui peut provenir de l’arrondi vers le haut ou vers le bas. Après cela, il y a le montant de total_staked_balance et total_stake_shares. Ensuite, nous créons de nouvelles actions avec eux. Enfin, nous mettons un journal et retournons le résultat. Ce 1 penny supplémentaire ou 1 yocto supplémentaire NEAR proviendra du fonds garanti lors de l’arrondi des actions. Nous avons facturé moins à l’utilisateur, mais nous avons contribué davantage au montant de ce 1 000 milliards de yocto NEAR que nous avions initialement désigné pour cela. Cette différence n’est généralement que de 1 yocto NEAR qui peut provenir de l’arrondi vers le haut ou vers le bas. Après cela, il y a le montant de total_staked_balance et total_stake_shares. Ensuite, nous créons de nouvelles actions avec eux. Enfin, nous mettons un journal et retournons le résultat. Après cela, il y a le montant de total_staked_balance et total_stake_shares. Ensuite, nous créons de nouvelles actions avec eux. Enfin, nous mettons un journal et retournons le résultat. Après cela, il y a le montant de total_staked_balance et total_stake_shares. Ensuite, nous créons de nouvelles actions avec eux. Enfin, nous mettons un journal et retournons le résultat.
Unstaking fonctionne de manière très similaire. Vous arrondissez au montant d’actions que vous devez payer. Ensuite, nous calculons le montant que vous recevez, en arrondissant à nouveau pour vous surpayer pour cela. Celle-ci provient également d’un fonds de garantie. Ensuite, nous diminuons les parts pour augmenter le montant et indiquons quand vous pouvez débloquer le solde entre quatre époques. Le unstake_amount est arrondi à l’inférieur afin que nous déposions un peu moins pour garantir le prix des autres participants de la cagnotte. C’est à peu près comme ça que fonctionne le pool de jalonnement et que les mathématiques fonctionnent. Nous compensons les erreurs d’arrondi à partir des fonds que nous avons alloués.
Conclusion
Nous avons mis à jour les clés ristretto lors de la conception de ce contrat et il était surprenant que nous devions en tenir compte. Dans le STAKE_SHARE_PRICE_GUARANTEE_FUND, 1 000 milliards de yocto NEAR devraient suffire pour 500 milliards de transactions, ce qui devrait être assez long pour le pool de staking afin qu’il ne puisse pas être rechargé car les récompenses seront immédiatement redistribuées au total_stake_balance au prochain ping. Nous avons consacré beaucoup de temps et d’efforts à ce contrat, car nous avons effectué des tonnes d’ examens de sécurité, y compris en interne et en externe, en particulier autour de ces mathématiques. C’était compliqué, et certaines choses ont été découvertes comme la clé ristretto qui est apparue lors des examens. Nousmarqué le journal des modifications de ce contrat, ainsi que dans le fichier readme, il y a un tas de choses qui sont apparues pendant le développement et les tests sur le système en direct, mais la version originale a pris environ une semaine à écrire. Plus tard, nous l’avons nettoyé, testé et amélioré. Ensuite, nous avons fait un tas de révisions. La mise en pause et la reprise ont été demandées par le pool, car sinon le propriétaire n’avait pas la possibilité de déjouer si son nœud tombe en panne. Ils attaqueront le réseau. Essentiellement, cet enjeu actif demanderait la validation et ne ferait pas fonctionner le réseau. Avant, nous n’avions pas de coupe. Ce n’était tout simplement pas un problème pour les participants, mais c’était un problème pour le réseau lui-même. De cette façon, le propriétaire peut suspendre le jalonnement s’il ne veut pas gérer le pool qu’ilmigrer dans le pool, et communiquer le plus possible avant cela. Ensuite, nous avons mis à jour l’interface de vote pour qu’elle corresponde au contrat de vote final de la phase deux. Nous avons ajouté des méthodes d’affichage d’assistance pour pouvoir interroger les comptes de manière lisible par l’homme. Enfin, il y a eu quelques améliorations autour des méthodes de traitement par lots ensemble, donc deposit_and_stake, stake_all, unstake_all et remove_all au lieu d’avoir d’abord à faire un appel de vue, à obtenir le montant et à mettre le montant pour appeler la mise. Voici la façon dont nous l’avons corrigé.
Lorsque vous stake, non seulement vous misez le montant, mais nous joignons également une promesse de vérifier si la mise a réussi. C’est nécessaire pour deux choses : vous si vous essayez de parier avec une clé invalide (pas une clé spécifique à ristretto), alors la promesse échouera avant l’exécution. La validation échoueraavant de l’envoyer, et cela fera en sorte que vous n’avez pas besoin de le vérifier dans le contrat. Il renverra le dernier appel, et tout ira bien. Nous avons également introduit la mise minimale au niveau du protocole. La mise minimale est d’un dixième du montant du prix du dernier siège, et si votre contrat essaie de miser moins que cela, l’action échouera et vous n’enverrez pas la promesse. Supposons que vous souhaitiez retirer une somme et que votre solde soit inférieur au dixième de la mise. L’action de jalonnement peut échouer, et vous n’allez pas dépiquer, alors que vous en avez besoin pour garantir que le dépouillement doit avoir lieu. Dans ce cas, nous avons ce rappel qui vérifie que l’action de staking s’est terminée avec succès. Ce rappel vérifie essentiellement que s’il échoue, et que le solde est positif, nous devons déjouer. Il appellera donc unstake pour une action où le montant de la mise est de zéro pour s’assurer que tout le solde est libéré. Vous pouvez vous retirer en 4 époques lors du test de ces contrats que nous avons fait sur le testnet beta 9 avant la maintenance. Le contrat était prêtpeut-être vers l’heure d’été, donc le test de cette itération a probablement pris entre 2 et 4 mois en raison de la complexité que cela implique pour interagir avec le protocole. Il y a eu beaucoup d’apprentissage de la pagination aux méthodes d’aide, et du regroupement de certaines choses. Une chose qui serait vraiment bien d’avoir une mise ou un dépôt et une mise sur un contrat de blocage. À l’heure actuelle, vous devez indiquer manuellement combien vous voulez miser sur un contrat de verrouillage, mais ce serait formidable si vous n’aviez pas besoin de penser à votre yocto NEAR et à combien il est verrouillé pour le stockage. Vous voulez juste tout mettre en jeu depuis votre verrouillage, mais comme il était déjà déployé, il était trop tard pour y penser. Il y a aussi du gaz qui est codé en dur, et avec le commundiminution des frais, ces numéros ne peuvent pas être modifiés car ils sont déjà sur la chaîne.
Donc le vote n’est pas important mais la méthode ON_STAKE_ACTION_GAS vous oblige à avoir un grand nombre pour chaque mise et vous ne pouvez pas le diminuer. Prendre des risques à chaque appel sur ce contrat nous obligera à avoir une grande quantité de gaz et le problème est que c’est du gaspillage. Disons que nous sommes d’accord pour brûler tout le gaz, ce gaz sera toujours brûlé et gaspillé et cela limite le nombre de transactions que vous pouvez mettre dans un bloc si nous restreignons le gaz en fonction de ce cas. Il y a eu beaucoup d’itérations sur les tests du contrat en utilisant le cadre de test de simulation que nous avons beaucoup amélioré. Si nous arrivons finalement aux contrats de verrouillage, vous pouvez voir comment la structure des contrats de verrouillage s’est améliorée par rapport à celui-ci.