Contrats intelligents - Comment mettre en œuvre des contrats intelligents évolutifs

1. Qu'est-ce qu'un contrat intelligent

En termes simples, un contrat intelligent est le code écrit sur la blockchain. Le code contient des règles rigoureuses et complètes. Une fois qu'un utilisateur satisfait aux règles et conditions du contrat, le code à l'intérieur sera déclenché pour exécuter une certaine méthode.

 

 2. Pourquoi rendre les contrats intelligents évolutifs

L'une des caractéristiques des contrats intelligents est qu'ils ne peuvent pas être modifiés après leur déploiement sur la chaîne.Ce mécanisme permet aux parties en interaction du contrat de faire confiance au contrat. Mais cela apporte également une série de problèmes, et si le contrat déployé trouve une vulnérabilité, celle-ci ne peut pas être corrigée. Si un bogue est trouvé, fatal, et doit être corrigé, comment le traiter ? Il s'agit d'utiliser le contrat pour réaliser une optimisation évolutive pour répondre à la demande

 

3. Le principe du mécanisme du contrat de mise à niveau

  1.   Qu'est-ce qu'un surclassement de contrat

Assurez-vous que les contrats qui ont été déployés sur la chaîne peuvent être optimisés et modifiés, tels que le code de la logique métier et les variables d'état sur la chaîne peuvent être ajoutées, supprimées et modifiées.

   2. Le principe du mécanisme de réalisation du contrat de mise à niveau

 Les méthodes de mise en œuvre actuelles ont différents modes selon la distinction de stockage, mais elles sont toutes indissociables d'un mécanisme de bas niveau, qui consiste à utiliser la fonctionnalité d'appel délégué pour réaliser le contrat évolutif, de manière à obtenir l'effet d'optimisation et de changement durables. du contrat.

Introduction à l'appel délégué

À l'heure actuelle, il existe trois façons principales d'appeler des contrats

  • appel
  • déléguéAppel
  • statiqueAppel

Point commun : ce sont toutes des méthodes pour appeler et exécuter l'adresse du contrat cible

Différence : L'environnement d'exécution de delegationCall est à l'opposé de call et staticCall.De ce fait, cette fonctionnalité peut être utilisée pour réaliser une évolutivité, et elle n'est pas perçue au niveau de l'utilisateur.

Pour une introduction spécifique à l'appel délégué, voir mon autre article

La différence entre Solidity - appel, appel délégué et code d'appel - Blog de Zeke Luo - Blog CSDN

 

4. Mettre en place des contrats ERC20 évolutifs

Présentation des codes

  • Rédigez le contrat de proxy InitializedProxy, la fonction principale de ce contrat est de transmettre et de stocker des données.

Héritez du contrat StorageSlotUpgradeable d'openzeppelin pour les classes d'utilitaires d'emplacement.

// SPDX-License-Identifier: GPL-3.0
import "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol";
pragma solidity >=0.7.0 <0.9.0;

contract InitializedProxy {
    // address of logic contract
    // slot bytes32(uint256(keccak256('EIP1967.PROXY.CONFTI.IMPLEMENTATION')) - 1)
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x5f62ce3c9aebd463c7a36ab1b244d2bb94f07a2c13889b3b687940ebc467b9b3;

    // ======== Constructor =========
    constructor(
        address logic,
        bytes memory initializationCalldata
    ) { 
        require(logic != address(0),"Proxy :: Wrong proxy contract address");
        StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = logic;
        // Delegatecall into the logic contract, supplying initialization calldata
        (bool _ok, bytes memory returnData) =
            logic.delegatecall(initializationCalldata);
        // Revert if delegatecall to implementation reverts
        require(_ok, string(returnData));
    }
     

    // ======== Fallback =========
    fallback() external payable {
        address _impl = StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
        assembly {
            let ptr := mload(0x40)
            calldatacopy(ptr, 0, calldatasize())
            let result := delegatecall(gas(), _impl, ptr, calldatasize(), 0, 0)
            let size := returndatasize()
            returndatacopy(ptr, 0, size)

            switch result
                case 0 {
                    revert(ptr, size)
                }
                default {
                    return(ptr, size)
                }
        }
    }

    // ======== Receive ===
     receive() external payable {} // solhint-disable-line no-empty-blocks

       function upgradeVersion(address newAddress_) public{ 
        StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newAddress_;
    }
}

1. Le constructeur constructeur a des données d'initialisation et enregistre le contrat de logique métier pointé

2. Fallback transmet la méthode de réception de tous les contrats de logique métier,

Méthode 3.upgradVersion pour la mise à niveau

Remplacer l'ancienne adresse de contrat logique de l'emplacement spécifié par un nouveau contrat logique

  • Implémentez votre propre contrat de logique métier (évolutif erc20)
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
contract logicA  is ERC20Upgradeable{
    
    function initialize(string memory tokenName_ ,string memory symbol_) initializer external {
        __ERC20_init(tokenName_, symbol_);
    }
    
    function mint(address account,uint256 amount)  external  {
        if(account != address(0) && amount > 0){
            _mint(account,amount);
        }
    }

    function burn(address account,uint256 amount)  external  {
        if(account != address(0) && amount > 0){
            _burn(account,amount);
        }
    } 
  
}
  • déployer le contrat d'usine

Le rôle principal de ce contrat est de créer des contrats logiques évolutifs et de gérer les mises à niveau, etc.

contract  testtFactory{
    
    address public logicProxy;
    
    function createProxy(address logiAddress_,string memory tokenName_,string memory symbol_) public {
            bytes memory _initializationCalldata = abi.encodeWithSignature(
            "initialize(string,string)",
            tokenName_,
            symbol_
        );
         logicProxy = address (new InitializedProxy(logiAddress_,_initializationCalldata));
    }
        
    function updateLogicProxy(address updataTemplate_) public { 

        (bool _ok, bytes memory returnData) = logicProxy.call(abi.encodeWithSignature(
            "upgradeVersion(address)",
             updataTemplate_
        ));

        require(_ok, string(returnData));
    } 

}

createProxy : génère un contrat de proxy évolutif

updateLogicProxy : met à jour le contrat

  • Le déploiement du contrat V2 est le contrat après la mise à niveau
contract logicA2 is ERC20Upgradeable{
    
    function mint(address account,uint256 amount)  external  {
        require (amount <= 10 ,"must be <= 10" );  
        if(account != address(0) && amount > 0){
            _mint(account,amount);
        }
    }

    function burn(address account,uint256 amount)  external  {
        if(account != address(0) && amount > 0){
            _burn(account,amount);
        }
    } 
  
}

Le montant de menthe modifié par ce contrat doit être inférieur ou égal à 10 pour une vérification logique après la mise à niveau.

 

5. Introduction à la logique d'utilisation du code ci-dessus

Prenez remix comme cas à utiliser :

1. Déployer le contrat de logique métier (le contrat erc20 peut évoluer)

7b2d9257688e4bd99cf252e64456a0cc.pngÉtape 2. Déployer le contrat d'usine 

e0b0b45f7eb34fef91b8a16110056722.png

La troisième étape appelle le contrat d'usine pour créer un contrat erc20Token évolutif

Appelez createProxy pour transmettre l'adresse du contrat erc20 évolutif créé à la première étape

Une fois la création réussie, cliquez sur logicProxy pour afficher l'adresse proxy générée

3f1b788ee44b423994f987f59fe162f0.png

 

Appelez ensuite la méthode at et sélectionnez le contrat logique correspondant à appeler (l'utilisation et le principe d'at peuvent être consultés par vous-même).

 

Étape 4 : Mettre à niveau le contrat erc20 actuel

Ouvrez le contrat d'usine et appelez updateLogicProxy pour transmettre l'adresse du nouveau contrat afin de terminer la mise à niveau. 

(Les utilisateurs n'hésitez pas à mettre à niveau)

 

5. Logique de mise à niveau

56c87094b0c44b8cb0c293a7a19deae1.png

 

⚠️ Notes de mise à niveau

1. Risque de conflit de créneaux horaires

2. Relation d'héritage après la mise à niveau


Résumer

Le risque de mise à niveau du contrat sera relativement important, essayez d'être strict, et la mise à niveau ne devrait qu'augmenter, ne pas diminuer et ne pas se modifier.

Ce qui précède est ce dont je veux parler aujourd'hui. Cet article ne présente que brièvement la mise à niveau et l'utilisation de delegationCall. En ce qui concerne la sécurité, vous devez encore ajouter des restrictions en fonction de votre entreprise. Si vous avez d'autres erreurs, veuillez le signaler, ou DM

 

 

Je suppose que tu aimes

Origine blog.csdn.net/qq_33842966/article/details/126681657
conseillé
Classement