Giter VIP home page Giter VIP logo

plutus's Introduction

Smart Contract con Plutus

馃彚 Universidad de Huelva (UHU)
馃搯 Curso 2020-2021
馃帗 Modelos Avanzados de Computaci贸n
:octocat: Ihar Myshkevich (@IgorMy)
:octocat: V铆ctor M. Rodr铆guez (@VictorNarov)

Introducci贸n

En este repositorio se documentar谩 la implementaci贸n de un Smart Contract codificado en lenguaje Haskell sobre plataforma Plutus Playground. En este, se visualiza c贸mo una cartera genera un contrato de transferencia de capital (Ada) y c贸mo la carpeta destinataria recoge ese capital.

Partes del Smart Contract

En este apartado veremos las diferentes partes de este Smart Contract.

Librer铆as

import Playground.Contract                                     -- Gesti贸n de contratos en el entorno Plutus Playground.
import           Control.Monad             (void)              -- Funci贸nes de c谩lculo avanzado.
import           Data.Aeson                (FromJSON, ToJSON)  -- Tipos y funciones para trabajar eficazmente con datos JSON.
import qualified Data.Text                 as T                -- Tipos y funciones para trabajar eficazmente con texto plano.
import           GHC.Generics              (Generic)           -- Funciones para la conversi贸n de datos.
import           Language.Plutus.Contract                      -- Contratos Pulutus.
import qualified Language.PlutusTx         as PlutusTx         -- Bibliotecas y el compilador para compilar Haskell en Plutus.
import           Language.PlutusTx.Prelude                     -- Sustituto del Haskell prelude que funciona mejor con PlutusTx.
import           Ledger                                        -- Contenedor para almacenar datos en bruto de una forma m谩s eficiente.
import qualified Ledger.Ada                as Ada              -- Almacenamiento de tipo Ada (moneda).
import qualified Ledger.Constraints        as Constraints      -- Restricciones del almacenamiento.
import qualified Ledger.Typed.Scripts      as Scripts          -- Funciones del almacenamiento.
import           Schema                                        -- Bilioteca Haskell para serializar y deserializar datos en JSON.
import           Wallet.Emulator.Wallet                        -- Biblioteca Haskell para gestionar carteras virtuales.

En este apatado importamos las librer铆as de CARDANO necesarias para la ejecuci贸n del Smart Contract. Su funcionalidad est谩 comentada a la derecha de su declaraci贸n.

Definici贸n de tipo de datos

data SmartContractData =
    SmartContractData
        { recipient :: PubKeyHash 
        , amount     :: Ada
        }
    deriving stock (Show, Generic)

PlutusTx.makeIsData ''SmartContractData
PlutusTx.makeLift ''SmartContractData

SmartContractData describe el destinatario al que se le va a enviar el capital y la cantidad de capital en Ada. Estamos utilizando el tipo PubKeyHash para identificar al destinatario. Al realizar el pago podemos utilizar el hash para crear la salida de clave p煤blica.

Script de validaci贸n

validateSmartContract :: SmartContractData -> () -> ValidatorCtx -> Bool
validateSmartContract SmartContractData{recipient, amount} _ ValidatorCtx{valCtxTxInfo} =
    Ada.fromValue (valuePaidTo valCtxTxInfo recipient) == amount

Esta funci贸n es muy importante. Su misi贸n es tomar ambas transacciones por separado y decidir si son v谩lidas. Solo en ese caso se ejecuta y se cierra el contrato. En nuestro caso, este script comprueba que la cantidad que recibir谩 el destinatario es la acordada por ambas partes.

Recoger peticiones

data LockArgs =
        LockArgs
            { recipientWallet :: Wallet -- Cartera del destinatario
            , totalAda         :: Ada   -- Cantidad (Ada) a vincular al contrato
            }
    deriving stock (Show, Generic)
    deriving anyclass (ToJSON, FromJSON, ToSchema)

type SmartContractSchema =
    BlockchainActions
        .\/ Endpoint "lock" LockArgs
        .\/ Endpoint "unlock" LockArgs

Para recoger las peticiones de los usuarios neceistamos declarar los "endpoints" correspondientes como parte del programa. El conjunto de todos los endpoints se denomina "schema". Lo construiremos usando el tipo Endpoint y el operador .\/ para combinarlos. Previamente hemos definido los par谩metros necesarios para los endpoints, que son la direcci贸n de la cartera destinataria y el cantidad de Ada a vincular con el contrato.
Se han desarrollado dos acciones para interactuar con el contrato lock y unlock.

lock :: Contract SmartContractSchema T.Text LockArgs
lock = endpoint @"lock"

unlock :: Contract SmartContractSchema T.Text LockArgs
unlock = endpoint @"unlock"

Endpoint recibe como argumento el nombre como tipo Haskell usando el operando @. En general el algoritmo de unificaci贸n de Haskell es lo suficientemente robusto para los tipos de argumentos pasados a una funci贸n. Pero hay algunos casos, como este, en los que es necesario indicarle el tipo de dato.

Funci贸n de transformaci贸n de datos
mkSmartContractData :: LockArgs -> SmartContractData
mkSmartContractData LockArgs{recipientWallet, totalAda} =
    let convert :: Wallet -> PubKeyHash
        convert = pubKeyHash . walletPubKey
    in
    SmartContractData
        { recipient = convert recipientWallet
        , amount = totalAda
        }

Para realizar correctamente la transferencia de un tipo wallet a otro, es necesario un objeto pubKeyHash. Es necesario convertir el valor del wallet a su Hash de clave p煤blica.

Vincular dinero al contrato

lockFunds :: SmartContractData -> Contract SmartContractSchema T.Text ()
lockFunds s@SmartContractData{amount} = do
    logInfo $ "Locking " <> show amount -- Muestra la cantidad de Ada vinculada al contrato por el registro
    let tx = Constraints.mustPayToTheScript s (Ada.toValue amount)
    void $ submitTxConstraints smartContractInstance tx

Con esta funci贸n vinculamos la cantidad obtenida del SmartContractData del usuario que inici贸 el contrato.

Obtener dinero del contrato

unlockFunds :: SmartContractData -> Contract SmartContractSchema T.Text ()
unlockFunds SmartContractData{recipient, amount} = do
    let contractAddress = (Ledger.scriptAddress (Scripts.validatorScript smartContractInstance))
    utxos <- utxoAt contractAddress
    let tx =
            collectFromScript utxos ()
            <> Constraints.mustPayToPubKey recipient (Ada.toValue $ amount)
    void $ submitTxConstraintsSpending smartContractInstance utxos tx

Mediante esta funci贸n el destinatario puede recibir el dinero que se ha depositado en el contrato. Gracias a la restricci贸n mustPayToPubKey con destinatario recipient y la cantidad de capital amount.
El script de validaci贸n verificar谩 que el destinatario haya solicitado la cantidad exacta vinculada al contrato por el remitente.

Interfaz de Plutus Playground

endpoints :: Contract SmartContractSchema T.Text ()
endpoints = (lock >>= lockFunds . mkSmartContractData) `select` (unlock >>= unlockFunds . mkSmartContractData)

mkSchemaDefinitions ''SmartContractSchema
$(mkKnownCurrencies [])

Estas 煤ltimas lineas definen nuestra aplicaci贸n para que se pueda ejecutar en Plutus Playground. La funci贸n select ofrece dos ramificaciones para las carteras. Por un lado permite transferir el capital al contrato ejecutando la funci贸n lockFunds y por otra, recibir el capital del contrato con la funci贸n unlockFunds. Asegura que una cartera solo pueda interactuar con una parte del contrato (enviar o recibir) y sea otra la que complemente el contrato.

Simulaci贸n

En esta simulaci贸n se puede visualizar la compilaci贸n de este Smart Contract en Plutus Playground y una ejecuci贸n en la que la cartera 1 envia 5 Ada a la cartera 2.

Bibliografia

plutus's People

Contributors

michaelpj avatar jmchapman avatar krisajenkins avatar j-mueller avatar shmish111 avatar effectfully avatar kwxm avatar gilligan avatar psygnisfive avatar nau avatar palas avatar brunjlar avatar polinavino avatar vmchale avatar mchakravarty avatar raduom avatar disassembler avatar nahern avatar bezirg avatar hrajchert avatar dk14 avatar wenkokke avatar simonjohnthompson avatar cubesoup avatar igormy avatar github-actions[bot] avatar merivale avatar victornarov avatar elviejo79 avatar omelkonian avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    馃枛 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 馃搳馃搱馃帀

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google 鉂わ笍 Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.