Nej Eth? Ingen tegnebog ?! Intet problem! Sådan får du din Dapp til at arbejde gasløs for de fattige Crypto Muggles

I denne artikel forklarer vi, hvordan du opgraderer en dApp til at arbejde med en hvilken som helst browser, uden selv at skulle installere en tegnebog først. Dette betyder, at brugere vil være i stand til at interagere med din dApp uden at skulle installere noget eller passere KYC / AML bare for at købe ETH for at betale for gasafgifter.

TabooKey's open source Gas Stations Network-projekt (EIP 1613), beskrevet i vores tidligere Ethereum-indlæg fra Yoav Weiss fra 1–800, er en gave, der ikke er bundet til strengene til Ethereum-samfundet, der hjælper dapper med at skaffe nye brugere ved at gøre sig tilgængelige for brugere, som enten har du overhovedet ikke en tegnebog, eller har ingen ETH i den, som indeholder stort set alle uklare jordplanter (bortset fra afrundingsfejlen hos de tidlige kryptodoptagere).

Normalt for at interagere med en Ethereum smart kontrakt, har brugere brug for en tegnebog, der har ETH i, til at betale for transaktionsgasafgift. Med et par enkle ændringer kan smarte kontrakter bruge TabooKey Tankstation Network til at tilføje svarende til et 1-800 gratis nummer, som brugere uden gas kan interagere med. I nogle brugssager behøver brugere ikke engang at oprette en tegnebog! Dette kan implementeres på en omhyggelig kontrolleret måde, der minimerer risikoen for misbrug.

Ethereum understøtter ikke dette direkte, så vi har brug for noget hjælp fra RelayHub-kontrakten og kædenettet fra RelayServers.

Der er fire trin til at konfigurere din dapp til understøttelse af gasløse transaktioner:

  1. Beslut om din adgangsmodel: Da du (kontraktsejeren) betaler for gassen, og klienterne får adgang til den gratis, skal du beslutte, hvilke klienter og hvilke opkald der har adgang til kontrakten.
    I vores eksempel tillader vi simpelthen enhver klient, men vi vil også vise, hvordan du kan oplade dine klienter på andre måder (f.eks. Oplade dem med symboler!).
  2. Rediger kontrakten for at acceptere videresendte opkald:
    Bemærk, at kontrakten altid accepterer "normalt" opkald. Vi tilføjer kun en mekanisme for at vide, hvem relæopkalderen er, når opkaldet kommer gennem et relæ.
  3. Ændre din klient: få din webapplikation (eller mobilapp) til at gå gennem relæet for at foretage opkald.
  4. Udfyld din kontrakts “gastank” for første gang. Da kontrakten betaler for opkaldene, er du (som kontraktsejeren) nødt til at finansiere den med jævne mellemrum, så den kan betale relæ-serverne for deres service.

Vi har allerede implementeret et eksempel “MetaCoin” -projekt, der bruger denne benzinfri model. Du er mere end velkommen til at eksperimentere her.

Nu hvor vi har talt om konceptet om, hvad vi laver, lad os dykke ind i emnet og forstå, hvordan vi konverterer det fra en "normal" dapp til en gasfri dapp.

Nogle bemærkninger om prøven:

  • Vi tilføjede en knap "Mint", så enhver bruger kan have indledende tokens at lege med.
  • Prøven viser, at den kan bruges med Metamask (kun til signering!) Eller uden den, med en flygtig nøgle gemt i en cookie.
    Bemærk, at Metamask-adressen er forskellig fra den uden Metamask. Du kan eksperimentere og flytte mønter mellem dem.

Dapp Access-model

Da du (kontraktsejeren) betaler for gassen på vegne af dine klienter, skal du beslutte, hvilke opkald, du ønsker at betale for.

De faktiske opkald til din dapp oprettes af et relæ, men endda et relæ kan ikke tvinge dig til at betale for et opkald. Hvis din kontrakt beslutter ikke at acceptere et opkald (ved din kode i accept_relayed_call () som vi vil se senere), vil selvom relæet lægger denne transaktion på blockchain, ikke kun det blive afvist, vil relæet betale for den afvisning. Du er dækket.

Mulige indstillinger som følger:

  • Gratis - lad enhver klient foretage et opkald (når alt kommer til alt bygger du også webapp'en, ikke?). Denne tilgang er fantastisk til en prøve-app (som vi gør her), men i den virkelige verden kan Eva, en ondsindet skuespiller, tage din webapp-kode, ændre den for at foretage gentagne opkald og udtømme dine penge. Eve vinder muligvis ikke noget - men Alice og Bob, dine legitime brugere, vil blive blokeret fra adgang til din tjeneste.
  • Kendte brugere - lad Alice og Bob, dine kendte brugere, få adgang til din kontrakt og blokere enhver anden. Det er en god tilgang, da hvis Bob forsøger at misbruge kontrakten, kan du blokere ham.
    Men der er et kylling-og-æg-problem: Hvordan kender du dine brugere? Alice og Bob skal logge ind første gang, så du kan kende dem.
  • Betaling med en anden metode - Forestil dig at du kan have en service, der betaler direkte i dine tokens. Du kan godt gøre det med en gasfri klient: Din kontrakt, JoeTokenContract, accepterer opkaldet fra Alice, bekræfter, at Alice har nok JoeTokens, og lader hende betale dig tilbage for transaktionen med hende JoeTokens.
    Du (kontraktsejeren) betaler stadig relæerne med ethergas, men Alice har betalt dig tilbage med JoeTokens.
  • Kombination - for at løse problemet med kendte brugere kan det være en god idé at acceptere “oprette-konto” -opkald fra nye brugere, og derefter begrænse opkald til kun kendte brugere. Alice, en ny bruger, logger ind på appen og løser måske en captcha for at bevise, at hun er menneskelig, og har lov til at kalde "oprette-konto" en gang. Efter registrering er Alice en kendt bruger og kan bruge resten af ​​kontrakten, lige så længe hun ikke misbruger denne tillid og får sig forbudt. Det er muligt at oprette sådanne komplekse regler, men vi beskriver dem ikke her.

Forudsætninger

Denne tutorial antager, at du udfører alle handlinger i et trøffelprojekt på din dapp. Du skal have npm installeret. Hvis du bruger linux, skal du sørge for, at du har npm version> 8 (mere specifikt skal du sørge for, at npx er tilgængelig).

For at køre et relæ lokalt bruger vores projekt en dockercontainer, så sørg for at du også har installeret docker. I stedet for, hvis du kører prøven mod “ropsten” testnet, kan du bruge det offentlige relænetværk, og docker er ikke påkrævet.

Installer prøvekontrakt

I det følgende afsnit ændrer vi prøven metamønten og tilføjer relæstøtte til den.

  • Download først prøven MetaCoin-projektet (bemærk, at du skal køre ganache-cli i et andet terminalvindue, før du kan køre “installere”):
git klon https://github.com/tabookey/metacoin.git
cd metacoin
npm installation
  • Vi tilføjede et "migrer" script kaldet 3_fund_metamask.jsto hjælpe med at finansiere Metamask-kontoen i det lokale miljø. Bare opdater din Metamask-adressekonto i dette script, så har du ether til at arbejde med hver gang du genstarter ganache.
  • Du kan testkøre det (før vi tilføjer vores relæstøtte til det) ved at starte "ganache" i et andet vindue og køre:
nxx-trøffel migreres
npm run dev
  • Bemærk, at denne prøve har en ekstra "mynt" -knap: hver konto har tilladelse til at præge sig 10000 mønter.

Tilføjelse af "gasfri" support til vores projekt

Først skal du medtage "tabookey-gasless" klient-lib i dit projekt:

npm installere tabookey-gasless

Nu skal vi starte vores ganache-knude og sørge for, at vi har en RelayHub-kontrakt installeret på den, og også en kørende relæ-server. Så stop ganache (hvis den kører) og kør (i et andet vindue):

npm udforsk tabookey-gasfri npm køre gsn-dock-relæ-ganache

Denne kommando kører et docker-billede, så det første kørsel vil tage nogen tid at downloade og starte. Det starter ganache, installerer en RelayHub på den og starter derefter en relayserver.

Det dumper en masse logfiler. Se efter "Udført registrering" logmeddelelse. Serveren fortsætter med at dumpe logfiler hvert minut, så den sidste linje siger: “Relæ er registreret for nylig. Ingen grund til at omregistrere ”. Relæet er nu klar til at acceptere opkald fra en klient.

Kontraktændringer

I dette trin vil vi ændre vores kontrakt (kontrakt / MetaCoin.sol), så den accepterer relæopkald.

Den første ting, en kontrakt skal gøre, er at arve fra RelayRecipient-kontrakt:

import “tabookey-gasless / kontrakter / RelayRecipient.sol”;
kontrakt MetaCoin er RelayRecipient

Nu skal du implementere metoderne for at lade RelayHub vide, hvilke anmodninger du accepterer. For returneringsværdier er alle heltal større end nul fejlkoder (note: 1, 2 er reserveret af RelayHub), mens returnering af nul betyder, at din kontrakt accepterer opkaldet. Implementeringen nedenfor accepterer simpelthen alle opkald. Senere tilføjer vi andre strategier.

funktion accept_relayed_call (adresse / * relæ * /, adresse / * fra * /,
    bytes / * kodet_funktion * /, uint / * gas_pris * /,
    uint / *action_fee * /) offentlig visning returnerer (uint32) {
  retur 0; // accepter alt.
}
// intet der skal gøres post-call.
// stadig, vi skal implementere denne metode.
funktion post_relayed_call (adresse / * relæ * /, adresse / * fra * /,
    bytes / * encoded_function * /, bool / * succes * /,
    uint / * used_gas * /, uint / *action_fee * /) public {
}

Dernæst skal du specificere det RelayHub, du accepterer anmodninger fra. Vi tilføjer en metode til at indstille hub-adressen. Bemærk, at i produktionskode skal denne metode være beskyttet for kun at blive kaldt af ejeren:

funktion init_hub (RelayHub hub_addr) offentlig {
    init_relay_hub (hub_addr);
}

I dit distributionsscript (2_deploy_contracts.js) skal du tilføje hub-adressen:

var ConvertLib = artifacts.require (‘./ ConvertLib.sol’)
var MetaCoin = artifacts.require (‘./ MetaCoin.sol’)
lad netværk = {
  'Ropsten': {
    relayHubAddr: '0x1349584869A1C7b8dc8AE0e93D8c15F5BB3B4B87'
  },
  'Udvikling': {
    relayHubAddr: '0x9C57C0F1965D225951FE1B2618C92Eefd687654F'
  }
}
var RelayHub = artifacts.require (‘./RelayHub.sol’)
module.exports = funktion (deployer, netværk) {
    deployer.deploy (ConvertLib)
    deployer.link (ConvertLib, MetaCoin)
    lad hubAddr = netværk [netværk] .relayHubAddr
    deployer.deploy (MetaCoin) .then (() => {
    let hub = RelayHub.at (hubAddr)
        return hub.depositFor (MetaCoin.address, {value: 1e18})
    }). derefter (() => {
        console.log (“== Initialisering af Metacoin's Hub”)
        returner MetaCoin.at (MetaCoin.address) .init_hub (hubAddr)
    }). fangst (e => {
        console.log (‘fejl:‘, e)
    })
}

Bemærk, at vi også kalder “depositFor”. Vi skal "finansiere" vores kontrakt, så den kan betale for den indgående transaktion (dette fungerer naturligvis kun på et lokalt netværk. Senere får vi se, hvordan man finansierer en kontrakt, der er implementeret til et offentligt netværk, som “ropsten ”).

På dette tidspunkt kan kontrakten acceptere videresendte opkald. Imidlertid ser alle anmodninger ud som om de kom fra en enkelt adresse - RelayHub, da det er det, variablen msg.sender Solidity er indstillet til. Vi kan ikke ændre msg.sender, så vi leverer en hjælpermetode i stedet. Du skal bruge get_sender () hvor som helst i din kontrakt, hvor msg.sender tidligere blev brugt.

Vær ikke bange - for normale opkald (ikke-videresendt) returnerer det ganske enkelt msg.sender. Men for opkald, der videresendes via vores RelayHub, returnerer det den rigtige opkalder.
For msg.data kan du bruge get_message_data () på lignende måde.

For eksempel kan en møntbalancemetode se ud:

funktion getBalance () offentlig visning returnerer (uint) {
    retursaldo [get_sender ()];
}

Det er det! Din kontrakt understøtter nu videresendte opkald. Bemærk, at kontrakten stadig kan bruges direkte uden relæ.

Klientændringer

Lad os nu ændre vores klientapplikation (app / scripts / index.js).

Tilføj i starten af ​​appen:

const tabookey = kræve (‘tabookey-gasless’)
const RelayProvider = tabookey.RelayProvider

Og ved din appstart (startfunktion) gør du:

var provider = new RelayProvider (web3.currentProvider, {
    txfee: 12,
    force_gasLimit: 500000
})
web3.setProvider (udbyder)

Det er alle de kodeændringer, du skal gøre. Fra dette tidspunkt bliver enhver kontrakt, du indlæser i din ansøgning, påberåbt via et relæ og koster ikke dine opkaldere noget. Appen fortsætter med at bruge Metamask, men kun til signering.

For at køre appen skal du sørge for, at “gsn-dock-relay-ganache” (forklaret ovenfor) kører i et andet vindue, og derefter køre:

nxx-trøffel migreres
npm run dev

Alle ovennævnte kilder tjekkes ind som "med-relæ" -gren på prøverepoen.

Finansier din kontrakt på et offentligt netværk

På dette tidspunkt kan du tænke "åh, det er dejligt, at min klient ikke behøver at betale for gassen - men hvem gør det?". Nå, din kontrakt betaler for gassen. Det kan ikke betale direkte, så du skal indsætte noget ether i RelayHub på vegne af din kontrakt, så det vil være i stand til at betale relæet for indgående opkald.

I den ganache-baserede prøve ovenfor tilføjede vi et opfordring til RelayHub.depositFor () til at finansiere kontrakten. Dette fungerer også, hvis du bruger trøffelmigrering til at distribuere din kontrakt til et offentligt netværk (som ropsten). Selvom du gør det, med tiden, når der foretages flere opkald til din kontrakt, vil depositumet udtømme, og du bliver nødt til at tilbagebetale din kontrakt.

Til dette formål oprettede vi et "Contract Manager" -værktøj til at kontrollere saldoen og deponere mere ether for en kontakt.

  • Åbn URL-adressen http://gsn.tabookey.com/webtools/contractmanager.html
  • Indtast adressen på din kontrakt
  • Klik på "genkontrol" for at kontrollere den aktuelle indestående saldo
  • Indtast den ønskede eth-balance, og klik på Indbetaling
  • Godkend pengeoverførslen i din Metamask-tegnebog

Arbejde uden metamask

Når vi ikke har brug for kundens tegnebog, er der ingen reel grund til at kræve, at Metamask er installeret. Lokale adresser, der opbevares i browseren (som en cookie) er muligvis nok. På denne måde kan dapp'en bruges fra enhver browser inklusive en hvilken som helst mobilbrowser.

Da vi ikke vil dykke ned i denne opsætning, kan du kontrollere kildemodifikationen i prøven "MetaCoin" i "relæ-uden-metamask" -grenen. Prøven lader brugeren beslutte, om han vil bruge Metamask, eller ikke, og hvis ikke, hvilket netværk, der skal tilsluttes, xdai eller ropsten. Derefter opretter den en midlertidig nøgle og gemmer den i en cookie.

Beskyttelse af din kontrakt

Ovenstående skema fungerer, men overlader din kontrakt's RelayHub-indskud sårbar. Enhver kan generere så mange opkald, som de vil, og dermed udtømme din kontrakts indbetaling, hvilket forhindrer opkald fra legitime brugere.

For eksempel kan vi lade brugeren betale for transaktionen med vores tokens:

Metoden accept_relayed_call () kan validere, at brugeren holder tokens, og post_relayed_call () trækker faktisk disse tokens fra hans konto.
Disse tokens fjernes ikke, hvis brugeren bruger direkte (uden relæ) opkald til kontrakten og betaler for transaktionen med ether.

Bemærk, at betalinger til relæerne stadig er i ether, så du som kontraktsejer skal være meget forsigtig med at håndtere konverteringskursen. Du kan se en prøvekontrakt på dette her såvel som andre opkaldsverificeringsmetoder.

Resumé

I ovenstående artikel har vi forklaret, hvordan en dapp kan bruge TabooKey Tankstation Network som et relæ til gasløse transaktioner, for at tillade klientopkald uden at betale for gas, og lade dappen bestemme, hvordan man får betalinger fra sine klienter .

I fremtidige artikler vil vi forsøge at forklare de tekniske detaljer i relænetværket, og vigtigst af alt, hvorfor det er sikret, og hvorfor ingen deltager i netværket (klient, relæ eller kontrakt) kan stjæle eller blokere nogen anden enhed.

Hvis du har spørgsmål eller forslag, er du velkommen til at kommentere her.