Cross-Virtual Machine: création d'un portail vers l'avenir des contrats intelligents

Introduction

Il s'est passé beaucoup de choses en 2022. L'ensemble de l'industrie Web3 a innové en matière de réalisations techniques, de résolution de problèmes réels et devient le terreau d'industries que nous n'avions jamais vues auparavant. Bien sûr, nous avons également été témoins de nombreux incidents et événements dont l'industrie doit apprendre et s'améliorer. Dire que 2022 s'est terminé en beauté serait un euphémisme dans l'espace Web3.

Cependant, la technologie ne peut que se développer, et vivre ces événements aide seulement les constructeurs à savoir ce qui fonctionne et ce qui ne fonctionne pas.

À la Fondation Astar, nous avons travaillé dur pour créer la fondation du futur, quelles que soient les influences extérieures qui se produisent actuellement. Et aujourd'hui, je suis fier de présenter l'une de nos fonctionnalités les plus importantes pour réaliser la vision Astar ; la machine virtuelle croisée (XVM). Cet article couvrira le rôle des contrats intelligents dans Web3, les problèmes que nous voyons dans la progression du développement dApp, pourquoi nous avons créé XVM, comment fonctionne XVM et, enfin, ce que l'avenir nous réserve.

Machines virtuelles de contrat intelligent WASM

WebAssembly (WASM) est un format de message que la machine virtuelle WebAssembly peut lire pour interpréter les codes d'octet WASM. Strictement parlant, WASM fait référence au format de message qui est compilé à partir d'un langage de niveau supérieur afin de communiquer avec le système dans un environnement virtuel. Mais par souci de simplicité, quand je dis WASM dans cet article, cela fera référence à la fois au WASM en tant que binaire et à la machine virtuelle dans la blockchain.

WASM a été utilisé à l'origine pour que le navigateur utilise un binaire compilé à partir d'un langage au niveau du système et crée une performance quasi native pour les applications Web. Mais grâce à la portabilité de WASM, cela peut également être exécuté en dehors du navigateur.

Étant donné que la machine virtuelle pour WASM est une machine virtuelle basée sur une pile (stack-based) comme la machine virtuelle Ethereum (EVM), il est possible de créer un environnement d'exécution de contrat intelligent, tant qu'il est compilé dans le binaire WASM. Contrairement à l'EVM, cela signifie que via WASM, il est possible de créer une blockchain qui exécute des contrats intelligents écrits dans des langages pouvant cibler WASM, tels que Rust, Go, C++, etc., qui prennent tous en charge la sécurité des types et une gestion appropriée des erreurs.

De plus, étant donné que la plupart des principaux langages pouvant être compilés vers WASM prennent en charge nativement les fonctions asynchrones dans leur syntaxe, il est possible d'introduire l'asynchronicité dans les contrats intelligents WASM. Pour l'interopérabilité, cela signifie que vous pouvez désormais gérer les fonctions inter-chaînes dans le contrat intelligent au lieu d'envoyer aveuglément des messages sans savoir quelle est la réponse. Étant donné que EVM et Solidity font défaut dans ce département, cela a des implications majeures pour la création d'applications natives de qualité industrielle et inter-chaînes en dehors de la DeFi. Basé sur de nombreux facteurs, WASM est l'avenir des contrats intelligents. Cependant, en raison du problème de compatibilité avec EVM, l'adoption massive de la technologie blockchain devient un défi.

La motivation derrière XVM

Nous savons tous que, techniquement parlant, les contrats intelligents basés sur WASM sont la voie à suivre. Cependant, il existe un défi majeur lors de l'adoption de contrats intelligents WASM dans un monde dominé par l'EVM. La plupart des équipes sont trop habituées au riche écosystème EVM. Parce que la plupart des écosystèmes WASM VM sont petits et trop étrangers, de nombreux projets existants ne voient pas l'avantage d'apprendre les contrats intelligents WASM à partir de zéro et sacrifient l'accès en faveur de l'écosystème EVM.

Nous avons créé XVM pour résoudre ce problème précis.

Les personnes qui nous connaissent depuis Plasm se souviendront peut-être que nous avons toujours été un réseau très intelligent axé sur les contrats WASM. Mais lorsque nous avons lancé Astar, nous l'avons lancé avec EVM au lieu de la palette contractuelle. Il s'agissait de démarrer l'écosystème et de fournir une plate-forme à un public plus large. Cependant, nous avons toujours prévu d'intégrer les contrats intelligents WASM dans l'écosystème plus large. C'est là que l'idée de XVM a commencé.

XVM est une palette personnalisée et un ensemble d'interfaces qui permettent à un contrat intelligent dans une machine virtuelle de communiquer avec une autre comme si elles se trouvaient dans le même environnement. En d'autres termes, avec XVM, vous pouvez créer en contrat ink! et accédez à tous les actifs ou contrats disponibles du côté EVM. De plus, si l'EVM d'Astar est connecté à une autre couche 0 comme Axelar ou Celer, vous pouvez créer un contrat intelligent ink! avec accès à toutes les chaînes EVM connectées à Axelar et Celer !

Les possibilités sont infinies avec cela, et nous espérons que XVM encouragera les constructeurs à développer des dApps innovantes sans faire le sacrifice de ne pas interagir avec un vaste écosystème EVM.

Les mécanismes de XVM

Alors, comment fonctionne XVM ? Le mécanisme réel est assez simple, car nous prenons un appel codé comme un tableau (inspiré du codec SCALE) et le transmettons comme argument à la palette XVM.

L'architecture

Voici l'architecture derrière XVM et comment il est connecté aux autres machines virtuelles.

Chacune de nos machines virtuelles de contrats intelligents aura un moyen d'exposer le module XVM pour permettre aux contrats intelligents d'autres environnements de les utiliser. Nous créons les fonctions pour chaque VM qui expose la fonction de palette XVM. Par exemple, la palette de contrats a des extensions de chaîne et le côté EVM a des contrats précompilés. Un contrat intelligent déployé d'un côté de la VM pourra interagir avec l'autre VM en envoyant l'appel encodé à l'extension de chaîne ou au contrat précompilé. Une fois la fonction XVM appelée, la palette appellera l'adaptateur de la machine virtuelle cible et transmettra l'appel de fonction au contrat intelligent cible. Du point de vue de la blockchain, cette ligne de transactions fera partie d'un seul bloc, ce qui la rendra entièrement transactionnelle. C'est ainsi qu'un appel XVM est effectué.

Utilisation de XVM

Maintenant que vous savez comment fonctionne un appel XVM, parlons de son fonctionnement du point de vue d'un développeur de contrats intelligents. Étant donné que le premier cas d'utilisation sera pour les développeurs ink! d'accéder aux actifs dans l'espace EVM, cette section se concentrera principalement sur l'utilisation de XVM à partir d'un contrat ink!. Mais veuillez noter que le même principe s'appliquera aux contrats Solidity sur EVM.

Pour effectuer un appel XVM à un contrat Solidity, tout ce dont vous avez besoin est l'adresse H160 EVM du contrat intelligent, le sélecteur de fonction et les arguments codés à transmettre à cette fonction.

Assez parlé ; voyons du vrai code.

//! ERC721 EVM contract interoperability using XVM interface.
#![cfg_attr(not(feature = "std"), no_std)]

pub use self::erc721::{
    Erc721,
    Erc721Ref,
};
use ink_lang as ink;

/// EVM ID (from astar runtime)
const EVM_ID: u8 = 0x0F;

/// The EVM ERC721 delegation contract.
#[ink::contract(env = xvm_environment::XvmDefaultEnvironment)]
mod erc721 {
    const APPROVE_SELECTOR: [u8; 4] = hex!["095ea7b3"];
    const TRANSFER_FROM_SELECTOR: [u8; 4] = hex!["23b872dd"];
    const MINT_SELECTOR: [u8; 4] = hex!["40c10f19"];

    use ethabi::{
        ethereum_types::{
            H160,
            U256,
        },
        Token,
    };
    use hex_literal::hex;
    use ink_prelude::vec::Vec;

    #[ink(storage)]
    pub struct Erc721 {
        evm_address: [u8; 20],
    }

    impl Erc721 {
        /// Create new ERC721 abstraction from given contract address.
        #[ink(constructor)]
        pub fn new(evm_address: [u8; 20]) -> Self {
            Self { evm_address }
        }

        #[ink(message)]
        pub fn transfer_from(&mut self, from: [u8; 20], to: [u8; 20], token_id: u128) -> bool {
            let encoded_input = Self::transfer_from_encode(from.into(), to.into(), token_id.into());
            self.env()
                .extension()
                .xvm_call(
                    super::EVM_ID,
                    Vec::from(self.evm_address.as_ref()),
                    encoded_input,
                )
                .is_ok()
        }

        #[ink(message)]
        pub fn approve(&mut self, to: [u8; 20], token_id: u128) -> bool {
            let encoded_input = Self::approve_encode(to.into(), token_id.into());
            self.env()
                .extension()
                .xvm_call(
                    super::EVM_ID,
                    Vec::from(self.evm_address.as_ref()),
                    encoded_input,
                )
                .is_ok()
        }

        #[ink(message)]
        pub fn mint(&mut self, to: [u8; 20], token_id: u128) -> bool {
            let encoded_input = Self::mint_encode(to.into(), token_id.into());
            self.env()
                .extension()
                .xvm_call(
                    super::EVM_ID,
                    Vec::from(self.evm_address.as_ref()),
                    encoded_input,
                )
                .is_ok()
        }

        fn transfer_from_encode(from: H160, to: H160, token_id: U256) -> Vec<u8> {
            let mut encoded = TRANSFER_FROM_SELECTOR.to_vec();
            let input = [
                Token::Address(from),
                Token::Address(to),
                Token::Uint(token_id),
            ];
            encoded.extend(&ethabi::encode(&input));
            encoded
        }

        fn approve_encode(to: H160, token_id: U256) -> Vec<u8> {
            let mut encoded = APPROVE_SELECTOR.to_vec();
            let input = [Token::Address(to), Token::Uint(token_id)];
            encoded.extend(&ethabi::encode(&input));
            encoded
        }

        fn mint_encode(to: H160, token_id: U256) -> Vec<u8> {
            let mut encoded = MINT_SELECTOR.to_vec();
            let input = [Token::Address(to), Token::Uint(token_id)];
            encoded.extend(&ethabi::encode(&input));
            encoded
        }
    }
}

C'est un contrat intelligent ink! qui peut contrôler un contrat ERC721 Solidity dans l'environnement EVM à l'aide de XVM. Cela a été extrait directement de notre référentiel de contrats XVM SDK. Vous pouvez voir que le contrat lui-même n'est pas grand-chose, mais essayons de le disséquer un peu.

/// EVM ID (from astar runtime)
const EVM_ID: u8 = 0x0F;

/// The EVM ERC721 delegation contract.
#[ink::contract(env = xvm_environment::XvmDefaultEnvironment)]
mod erc721 {
    const APPROVE_SELECTOR: [u8; 4] = hex!["095ea7b3"];
    const TRANSFER_FROM_SELECTOR: [u8; 4] = hex!["23b872dd"];
    const MINT_SELECTOR: [u8; 4] = hex!["40c10f19"];

L'EVM_ID fait référence à l'ID de la VM, qui est nécessaire pour que XVM comprenne quelle VM ce contrat ciblera. Comme il s'agit d'un ID, nous pouvons étendre XVM pour prendre en charge n'importe quel nombre de VM de contrat intelligent et leur permettre de communiquer entre elles.

La seconde moitié de l'extrait définit les sélecteurs de fonction que ce contrat utilisera comme constante.

   #[ink(storage)]
    pub struct Erc721 {
        evm_address: [u8; 20],
    }

    impl Erc721 {
        /// Create new ERC721 abstraction from given contract address.
        #[ink(constructor)]
        pub fn new(evm_address: [u8; 20]) -> Self {
            Self { evm_address }
        }

La partie suivante du code définit l'adresse H160 (notez que [u8; 20] signifie un tableau de 20 octets, soit 160 bits) à laquelle nous voulons envoyer le message. Pour cet exemple, nous laissons l'utilisateur définir l'adresse lors du déploiement en tant que constructeur, mais ce comportement est entièrement personnalisable tant que nous avons une adresse EVM valide.


        #[ink(message)]
        pub fn transfer_from(&mut self, from: [u8; 20], to: [u8; 20], token_id: u128) -> bool {
            let encoded_input = Self::transfer_from_encode(from.into(), to.into(), token_id.into());
            self.env()
                .extension()
                .xvm_call(
                    super::EVM_ID,
                    Vec::from(self.evm_address.as_ref()),
                    encoded_input,
                )
                .is_ok()
        }

        #[ink(message)]
        pub fn approve(&mut self, to: [u8; 20], token_id: u128) -> bool {
            let encoded_input = Self::approve_encode(to.into(), token_id.into());
            self.env()
                .extension()
                .xvm_call(
                    super::EVM_ID,
                    Vec::from(self.evm_address.as_ref()),
                    encoded_input,
                )
                .is_ok()
        }

        #[ink(message)]
        pub fn mint(&mut self, to: [u8; 20], token_id: u128) -> bool {
            let encoded_input = Self::mint_encode(to.into(), token_id.into());
            self.env()
                .extension()
                .xvm_call(
                    super::EVM_ID,
                    Vec::from(self.evm_address.as_ref()),
                    encoded_input,
                )
                .is_ok()
        }

La section suivante déclare les fonctions appelables de contrat public avec lesquelles le client va interagir. Cette fonction est l'endroit où le contrat appelle la palette XVM via les extensions de chaîne.

 self.env()
                .extension()
                .xvm_call(
                    super::EVM_ID,
                    Vec::from(self.evm_address.as_ref()),
                    encoded_input,
                )
                .is_ok()

Les arguments pour le XVM sont simples. Vous transmettez l'ID de la machine virtuelle, l'adresse du contrat avec lequel vous souhaitez interagir et les arguments codés de la fonction, y compris son sélecteur. Après cela, la palette XVM fera l'appel au contrat du côté EVM. Mais comment fonctionne l'encodage ?

   fn transfer_from_encode(from: H160, to: H160, token_id: U256) -> Vec<u8> {
            let mut encoded = TRANSFER_FROM_SELECTOR.to_vec();
            let input = [
                Token::Address(from),
                Token::Address(to),
                Token::Uint(token_id),
            ];
            encoded.extend(&ethabi::encode(&input));
            encoded
        }

        fn approve_encode(to: H160, token_id: U256) -> Vec<u8> {
            let mut encoded = APPROVE_SELECTOR.to_vec();
            let input = [Token::Address(to), Token::Uint(token_id)];
            encoded.extend(&ethabi::encode(&input));
            encoded
        }

        fn mint_encode(to: H160, token_id: U256) -> Vec<u8> {
            let mut encoded = MINT_SELECTOR.to_vec();
            let input = [Token::Address(to), Token::Uint(token_id)];
            encoded.extend(&ethabi::encode(&input));
            encoded
        }

La dernière section du code est l'endroit où tout l'encodage est géré. Vous pouvez voir que le schéma d'encodage ajoute au sélecteur de fonction un tableau d'arguments encodés via la bibliothèque ethabi Rust.

Essayez-le maintenant

XVM est actuellement en direct sur notre testnet public, Shibuya ! Vous pouvez essayer cette dernière fonctionnalité immédiatement. Nous avons également préparé quelques référentiels pour supporter les développeurs qui souhaitent utiliser XVM.

ink! XVM SDK

Comme vous l'avez peut-être vu dans la section précédente, l'utilisation de XVM à partir d'un contrat intelligent est simple. Mais pour rendre le processus de développement encore plus facile, nous avons préparé un SDK XVM pour les interfaces couramment utilisées dans le monde des machines virtuelles EVM et WASM.

S'il vous plaît jetez un œil au référentiel XVM SDK pour créer en contrats ink! pouvant contrôler ERC20, ERC721, etc. Avec l'aide de la communauté, nous pouvons étendre le SDK pour prendre en charge davantage d'interfaces, créer un SDK pour Solidity et Ask !, et créer des exemples de dApps pouvant exploiter XVM.

Application Workshop Sub0 XVM

Si vous souhaitez en savoir plus sur XVM en action avec une dApp full-stack, ne cherchez pas plus loin que le référentiel Sub0 XVM Workshop, le projet que j'ai utilisé pour présenter les capacités de XVM au public pour la toute première fois à Sub0. Cette dApp simple montre comment vous pouvez contrôler un jeton ERC20 à partir des signataires natifs EVM et Substrate. Vous pouvez également consulter Astar Tech Talk sur XVM.

Applications

Malgré la simplicité de XVM, nous pouvons créer de nombreuses applications potentielles qui font plus que combler la liquidité d'EVM à WASM VM. Avec XVM, vous pouvez prouver la propriété d'actifs qui résident dans un environnement différent à partir d'un schéma de compte différent (par exemple : transfert de propriété d'un jeton EVM ERC20 en utilisant uniquement un portefeuille Polkadot-js). Cela signifie que vous n'avez pas besoin de créer un nouveau portefeuille pour chaque environnement afin de contrôler tous les actifs. En d'autres termes, nous pouvons créer un contrôleur d'actifs universel avec un seul signataire.

Par exemple, de nombreux marchés NFT n'autorisent actuellement que les signataires EVM comme MetaMask. Une exception est Singular sur Kusama. Vous ne pouvez donc pas échanger ou mettre aux enchères un NFT ERC721 en utilisant Polkadot-js ou RMRK NFT en utilisant MetaMask. Avec XVM, nous pouvons résoudre ce problème en permettant aux deux signataires de gérer et de transférer la propriété de n'importe quelle norme NFT sur EVM et WASM VM. Permettre une opportunité UX plus large. En d'autres termes, les utilisateurs peuvent explorer différents types de NFT sur plusieurs marchés sans quitter leur interface de portefeuille préférée.

D'autres applications se font via des dApps inter-chain, où nous prenons le même schéma de codage de XVM. Grâce à Astar Network, les dApps peuvent interagir avec un contrat intelligent dans un environnement complètement étranger comme Solana ou Near, étant donné que nous avons un protocole sécurisé de transmission de messages à consensus croisé comme XCMP sur Polkadot.

Sky is the limit en ce qui concerne XVM, et nous espérons qu'avec cela, les contrats intelligents à l'avenir fonctionneront de manière transparente, quel que soit le langage avec lequel ils sont écrits ou l'environnement/RPC qu'ils utilisent.

L'avenir

Actuellement, le XVM est en v2, et nous travaillons dur pour créer la v3. L'une des limitations de la v2 est l'absence de requête de stockage XVM et de messages d'erreur. Lorsqu'ils interagissent avec un contrat intelligent, les développeurs s'attendent à interroger certaines valeurs telles que la quantité de jeton ERC20 détenue par un compte dans le cadre de leur logique d'application. Avec la v3, nous autoriserons les contrats intelligents à lire la valeur de stockage d'un contrat intelligent à partir d'un environnement différent. Comme pour les messages d'erreur, les développeurs ne savent que si la transaction a réussi. Mais avec des messages d'erreur améliorés, nous pouvons permettre au projet de gérer correctement les cas particuliers dans leur dApp.

Pour l'avenir de XVM, nous voulons l'intégrer à XCMP afin que les contrats intelligents sur Astar puissent appeler des contrats intelligents sur d'autres parachains, quelle que soit la machine virtuelle qu'ils utilisent. Cela permettra aux développeurs de créer une application dApp native véritablement inter-chain et d'étendre la fonctionnalité des contrats intelligents à quelque chose que nous n'aurions jamais pu faire auparavant.

Enfin, nous ne pouvons pas nous appeler une chaîne multi-VM en n'ayant que l'EVM et la palette de contrats. À l'avenir, nous ajouterons une autre machine virtuelle capable de gérer nativement l'asynchronicité pour les contrats intelligents et d'abstraire tous les appels inter-chaînes en tant que fonction asynchrone. Cette machine virtuelle sera compatible avec XVM, permettant à toutes les dApps sur le réseau Astar d'utiliser pleinement les capacités des fonctions cross-chain sans avoir à forcer les utilisateurs à créer un autre compte dans une chaîne différente ou à déployer une autre dApp.

Conclusion

Vous pouvez voir qu'avec XVM, nous pouvons éliminer les problèmes qui surviennent lors de la fusion de l'écosystème de blockchain traditionnelles dominées par EVM et permettre à un nouveau paradigme de projets dApp d'entrer dans notre écosystème sans sacrifier l'accès au vaste écosystème fourni par EVM.

Avec les contrats intelligents WASM, nous voyons un avenir où les projets peuvent accéder et utiliser d'autres blockchains avec une simple fonction asynchrone ; les projets n'ont pas à craindre le type de sécurité qui manque à Solidity lors de l'élaboration d'un contrat intelligent ; et augmenter le bassin de talents et la diversité des projets grâce à la capacité linguistique étendue de WASM.

Et grâce à XVM, nous permettons aux projets de se concentrer sur la création de ce qui apporte de la valeur aux utilisateurs finaux sans se soucier de ce qu'ils manquent en construisant avec WASM.

Astar Network est le point de départ de votre innovation.

Website | Twitter | Discord | Telegram | GitHub | Reddit

0

Astar Network est une blockchain Substrate, hub de smart contracts évolutive sur Polkadot. Elle intègre des solutions Layer 2 et inter-chaînes. Astar prend en charge les environnements WASM (Polkadot) et EVM (Ethereum).

0 comments

Astar Network est une blockchain Substrate, hub de smart contracts évolutive sur Polkadot. Elle intègre des solutions... Show More